1 /* ----------------------------------------------------------------------- *
3 * Copyright 2009 Pierre-Alexandre Meyer
5 * Some parts borrowed from chain.c32:
7 * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
8 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
10 * This file is part of Syslinux, and is made available under
11 * the terms of the GNU General Public License version 2.
13 * ----------------------------------------------------------------------- */
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>
23 static int is_extended_partition(struct part_entry
*ptab
)
25 return (ptab
->ostype
== 0x05 ||
26 ptab
->ostype
== 0x0f || ptab
->ostype
== 0x85);
29 static int msdos_magic_present(const char *ptab
)
31 return (*(uint16_t *) (ptab
+ 0x1fe) == 0xaa55);
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
44 static int process_extended_partition(struct driveinfo
*drive_info
,
45 const int partition_offset
,
47 p_callback callback
, int nb_part_seen
)
50 /* The ebr is located at the first sector of the extended partition */
51 char *ebr
= malloc(SECTOR
* sizeof(char));
53 if (read_sectors(drive_info
, ebr
, partition_offset
+ ebr_offset
, 1) == -1)
56 /* Check msdos magic signature */
57 if (!msdos_magic_present(ebr
))
60 struct part_entry
*ptab
=
61 (struct part_entry
*)(ebr
+ PARTITION_TABLES_OFFSET
);
63 for (int i
= 0; i
< 4; i
++) {
67 if (!is_extended_partition(&ptab
[i
])) {
69 * This EBR partition table entry points to the
70 * logical partition associated to that EBR
72 int logical_partition_start
= ebr_offset
+ ptab
[i
].start_lba
;
74 /* Last EBR in the extended partition? */
75 if (!logical_partition_start
)
80 * 3rd and 4th entries in an EBR should be zero
81 * Some (malformed) partitioning software still add some
82 * data partitions there.
84 if (ptab
[i
].start_lba
<= 0 || ptab
[i
].length
<= 0)
90 partition_offset
+ logical_partition_start
, nb_part_seen
);
92 status
= process_extended_partition(drive_info
,
95 callback
, nb_part_seen
);
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
112 static int process_mbr(struct driveinfo
*drive_info
, struct part_entry
*ptab
,
117 for (int i
= 0; i
< 4; i
++) {
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);
125 process_extended_partition(drive_info
, ptab
[i
].start_lba
, 0,
128 callback(drive_info
, &ptab
[i
], ptab
[i
].start_lba
, i
+ 1);
136 * parse_partition_table - execute a callback for each partition entry
137 * @d: driveinfo struct describing the drive
138 * @callback: Callback to execute
140 * The signature of the callback should be the following:
142 * void callback(struct driveinfo *drive_info,
143 * struct part_entry *ptab,
147 int parse_partition_table(struct driveinfo
*d
, p_callback callback
)
149 char *mbr
= malloc(SECTOR
* sizeof(char));
151 if (read_mbr(d
->disk
, mbr
) == -1)
154 /* Check msdos magic signature */
155 if (!msdos_magic_present(mbr
))
158 struct part_entry
*ptab
=
159 (struct part_entry
*)(mbr
+ PARTITION_TABLES_OFFSET
);
160 return process_mbr(d
, ptab
, callback
);