source: bootcd/isolinux/syslinux-6.03/com32/gpllib/disk/msdos.c @ dd1be7c

Last change on this file since dd1be7c was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 4.4 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2009 Pierre-Alexandre Meyer
4 *
5 *   Some parts borrowed from chain.c32:
6 *
7 *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
8 *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
9 *
10 *   This file is part of Syslinux, and is made available under
11 *   the terms of the GNU General Public License version 2.
12 *
13 * ----------------------------------------------------------------------- */
14
15#include <stdlib.h>
16
17#include <disk/common.h>
18#include <disk/geom.h>
19#include <disk/msdos.h>
20#include <disk/partition.h>
21#include <disk/read.h>
22
23static int is_extended_partition(struct part_entry *ptab)
24{
25    return (ptab->ostype == 0x05 ||
26            ptab->ostype == 0x0f || ptab->ostype == 0x85);
27}
28
29static int msdos_magic_present(const char *ptab)
30{
31    return (*(uint16_t *) (ptab + 0x1fe) == 0xaa55);
32}
33
34/**
35 * process_extended_partition - execute a callback for each partition contained listed in an ebr
36 * @drive_info:         driveinfo struct describing the drive
37 * @partition_offset:   Absolute start (lba) of the extended partition
38 * @ebr_offset:         Relative start (lba) of the current ebr processed within
39 *                      the extended partition
40 * @callback:           Callback to execute
41 * @error:              Buffer for I/O errors
42 * @nb_part_seen:       Number of partitions found on the disk so far
43 **/
44static int process_extended_partition(struct driveinfo *drive_info,
45                                      const int partition_offset,
46                                      const int ebr_offset,
47                                      p_callback callback, int nb_part_seen)
48{
49    int status = 0;
50    /* The ebr is located at the first sector of the extended partition */
51    char *ebr = malloc(SECTOR * sizeof(char));
52
53    if (read_sectors(drive_info, ebr, partition_offset + ebr_offset, 1) == -1)
54        goto abort;
55
56    /* Check msdos magic signature */
57    if (!msdos_magic_present(ebr))
58        goto abort;
59
60    struct part_entry *ptab =
61        (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET);
62
63    for (int i = 0; i < 4; i++) {
64        if (status == -1)
65            goto abort;
66
67        if (!is_extended_partition(&ptab[i])) {
68            /*
69             * This EBR partition table entry points to the
70             * logical partition associated to that EBR
71             */
72            int logical_partition_start = ebr_offset + ptab[i].start_lba;
73
74            /* Last EBR in the extended partition? */
75            if (!logical_partition_start)
76                continue;
77
78            /*
79             * Check for garbage:
80             * 3rd and 4th entries in an EBR should be zero
81             * Some (malformed) partitioning software still add some
82             * data partitions there.
83             */
84            if (ptab[i].start_lba <= 0 || ptab[i].length <= 0)
85                continue;
86
87            nb_part_seen++;
88            callback(drive_info,
89                     &ptab[i],
90                     partition_offset + logical_partition_start, nb_part_seen);
91        } else
92            status = process_extended_partition(drive_info,
93                                                partition_offset,
94                                                ptab[i].start_lba,
95                                                callback, nb_part_seen);
96    }
97
98    free(ebr);
99    return 0;
100
101abort:
102    free(ebr);
103    return -1;
104}
105
106/**
107 * process_mbr - execute a callback for each partition contained in an {m,e}br
108 * @drive_info: driveinfo struct describing the drive
109 * @ptab:       Pointer to the partition table
110 * @callback:   Callback to execute
111 **/
112static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab,
113                       p_callback callback)
114{
115    int status = 0;
116
117    for (int i = 0; i < 4; i++) {
118        if (status == -1)
119            return -1;
120
121        if (ptab[i].start_sect > 0) {
122            if (is_extended_partition(&ptab[i])) {
123                callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1);
124                status =
125                    process_extended_partition(drive_info, ptab[i].start_lba, 0,
126                                               callback, 4);
127            } else
128                callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1);
129        }
130    }
131
132    return 0;
133}
134
135/**
136 * parse_partition_table - execute a callback for each partition entry
137 * @d:          driveinfo struct describing the drive
138 * @callback:   Callback to execute
139 *
140 * The signature of the callback should be the following:
141 *
142 * void callback(struct driveinfo *drive_info,
143 *               struct part_entry *ptab,
144 *               int offset_root,
145 *               int nb_part_seen)
146 **/
147int parse_partition_table(struct driveinfo *d, p_callback callback)
148{
149    char *mbr = malloc(SECTOR * sizeof(char));
150
151    if (read_mbr(d->disk, mbr) == -1)
152        return -1;
153    else {
154        /* Check msdos magic signature */
155        if (!msdos_magic_present(mbr))
156            return -1;
157
158        struct part_entry *ptab =
159            (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET);
160        return process_mbr(d, ptab, callback);
161    }
162}
Note: See TracBrowser for help on using the repository browser.