1 /* ----------------------------------------------------------------------- *
3 * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
4 * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
5 * Copyright 2010 Shao Miller
6 * Copyright 2010-2012 Michal Soltys
8 * Permission is hereby granted, free of charge, to any person
9 * obtaining a copy of this software and associated documentation
10 * files (the "Software"), to deal in the Software without
11 * restriction, including without limitation the rights to use,
12 * copy, modify, merge, publish, distribute, sublicense, and/or
13 * sell copies of the Software, and to permit persons to whom
14 * the Software is furnished to do so, subject to the following
17 * The above copyright notice and this permission notice shall
18 * be included in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
29 * ----------------------------------------------------------------------- */
34 * Provides disk / partition iteration.
42 #include <syslinux/disk.h>
46 #define ost_is_ext(type) ((type) == 0x05 || (type) == 0x0F || (type) == 0x85)
47 #define ost_is_nondata(type) (ost_is_ext(type) || (type) == 0x00)
48 #define sane(s,l) ((s)+(l) > (s))
50 /* virtual forwards */
52 static void pi_dtor_(struct part_iter
*);
53 static int pi_next_(struct part_iter
*);
54 static int pi_dos_next(struct part_iter
*);
55 static int pi_gpt_next(struct part_iter
*);
59 static struct itertype types
[] = {
71 const struct itertype
* const typedos
= types
;
72 const struct itertype
* const typegpt
= types
+1;
73 const struct itertype
* const typeraw
= types
+2;
75 /* pi_dtor_() - common/raw iterator cleanup */
76 static void pi_dtor_(struct part_iter
*iter
)
78 /* syslinux's free is null resilient */
82 /* pi_ctor() - common/raw iterator initialization */
83 static int pi_ctor(struct part_iter
*iter
,
84 const struct disk_info
*di
, int flags
87 memcpy(&iter
->di
, di
, sizeof *di
);
90 iter
->length
= di
->lbacnt
;
96 /* pi_dos_ctor() - MBR/EBR iterator specific initialization */
97 static int pi_dos_ctor(struct part_iter
*iter
,
98 const struct disk_info
*di
, int flags
,
99 const struct disk_dos_mbr
*mbr
102 if (pi_ctor(iter
, di
, flags
))
105 if (!(iter
->data
= malloc(sizeof *mbr
))) {
110 memcpy(iter
->data
, mbr
, sizeof *mbr
);
112 iter
->dos
.bebr_index0
= -1;
113 iter
->dos
.disk_sig
= mbr
->disk_sig
;
115 iter
->type
= typedos
;
122 /* pi_gpt_ctor() - GPT iterator specific initialization */
123 static int pi_gpt_ctor(struct part_iter
*iter
,
124 const struct disk_info
*di
, int flags
,
125 const struct disk_gpt_header
*gpth
, const struct disk_gpt_part_entry
*gptl
130 if (pi_ctor(iter
, di
, flags
))
133 siz
= (uint64_t)gpth
->part_count
* gpth
->part_size
;
135 if (!(iter
->data
= malloc((size_t)siz
))) {
140 memcpy(iter
->data
, gptl
, (size_t)siz
);
142 iter
->gpt
.pe_count
= (int)gpth
->part_count
;
143 iter
->gpt
.pe_size
= (int)gpth
->part_size
;
144 iter
->gpt
.ufirst
= gpth
->lba_first_usable
;
145 iter
->gpt
.ulast
= gpth
->lba_last_usable
;
147 memcpy(&iter
->gpt
.disk_guid
, &gpth
->disk_guid
, sizeof gpth
->disk_guid
);
148 memcpy(&iter
->gpt
.part_guid
, &gpth
->disk_guid
, sizeof gpth
->disk_guid
);
150 iter
->type
= typegpt
;
157 /* Logical partition must be sane, meaning:
158 * - must be data or empty
159 * - must have non-0 start and length
160 * - values must not wrap around 32bit
161 * - must be inside current EBR frame
164 static int notsane_logical(const struct part_iter
*iter
)
166 const struct disk_dos_part_entry
*dp
;
169 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
;
174 if (ost_is_ext(dp
[0].ostype
)) {
175 error("The 1st EBR entry must be data or empty.");
179 if (!(iter
->flags
& PIF_STRICT
))
182 end_log
= dp
[0].start_lba
+ dp
[0].length
;
184 if (!dp
[0].start_lba
||
186 !sane(dp
[0].start_lba
, dp
[0].length
) ||
187 end_log
> iter
->dos
.nebr_siz
) {
189 error("Logical partition (in EBR) with invalid offset and/or length.");
196 /* Extended partition must be sane, meaning:
197 * - must be extended or empty
198 * - must have non-0 start and length
199 * - values must not wrap around 32bit
200 * - must be inside base EBR frame
203 static int notsane_extended(const struct part_iter
*iter
)
205 const struct disk_dos_part_entry
*dp
;
208 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
;
213 if (!ost_is_nondata(dp
[1].ostype
)) {
214 error("The 2nd EBR entry must be extended or empty.");
218 if (!(iter
->flags
& PIF_STRICT
))
221 end_ebr
= dp
[1].start_lba
+ dp
[1].length
;
223 if (!dp
[1].start_lba
||
225 !sane(dp
[1].start_lba
, dp
[1].length
) ||
226 end_ebr
> iter
->dos
.bebr_siz
) {
228 error("Extended partition (EBR) with invalid offset and/or length.");
235 /* Primary partition must be sane, meaning:
236 * - must have non-0 start and length
237 * - values must not wrap around 32bit
240 static int notsane_primary(const struct part_iter
*iter
)
242 const struct disk_dos_part_entry
*dp
;
243 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
+ iter
->index0
;
248 if (!(iter
->flags
& PIF_STRICT
))
251 if (!dp
->start_lba
||
253 !sane(dp
->start_lba
, dp
->length
) ||
254 ((iter
->flags
& PIF_STRICTER
) && (dp
->start_lba
+ dp
->length
> iter
->di
.lbacnt
))) {
255 error("Primary partition (in MBR) with invalid offset and/or length.");
262 static int notsane_gpt(const struct part_iter
*iter
)
264 const struct disk_gpt_part_entry
*gp
;
265 gp
= (const struct disk_gpt_part_entry
*)
266 (iter
->data
+ iter
->index0
* iter
->gpt
.pe_size
);
268 if (guid_is0(&gp
->type
))
271 if (!(iter
->flags
& PIF_STRICT
))
274 if (gp
->lba_first
< iter
->gpt
.ufirst
||
275 gp
->lba_last
> iter
->gpt
.ulast
) {
276 error("LBA sectors of GPT partition are beyond the range allowed in GPT header.");
283 static int dos_next_mbr(struct part_iter
*iter
, uint32_t *lba
,
284 struct disk_dos_part_entry
**_dp
)
286 struct disk_dos_part_entry
*dp
;
288 while (++iter
->index0
< 4) {
289 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
+ iter
->index0
;
291 if (notsane_primary(iter
)) {
292 iter
->status
= PI_INSANE
;
296 if (ost_is_ext(dp
->ostype
)) {
297 if (iter
->dos
.bebr_index0
>= 0) {
298 error("More than 1 extended partition.");
299 iter
->status
= PI_INSANE
;
302 /* record base EBR index */
303 iter
->dos
.bebr_index0
= iter
->index0
;
305 if (!ost_is_nondata(dp
->ostype
) || (iter
->flags
& PIF_STEPALL
)) {
306 *lba
= dp
->start_lba
;
315 static int prep_base_ebr(struct part_iter
*iter
)
317 struct disk_dos_part_entry
*dp
;
319 if (iter
->dos
.bebr_index0
< 0) /* if we don't have base extended partition at all */
321 else if (!iter
->dos
.bebr_lba
) { /* if not initialized yet */
322 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
+ iter
->dos
.bebr_index0
;
324 iter
->dos
.bebr_lba
= dp
->start_lba
;
325 iter
->dos
.bebr_siz
= dp
->length
;
327 iter
->dos
.nebr_lba
= dp
->start_lba
;
328 iter
->dos
.nebr_siz
= dp
->length
;
335 static int dos_next_ebr(struct part_iter
*iter
, uint32_t *lba
,
336 struct disk_dos_part_entry
**_dp
)
338 struct disk_dos_part_entry
*dp
;
340 if (prep_base_ebr(iter
) < 0) {
341 iter
->status
= PI_DONE
;
345 while (++iter
->index0
< 1024 && iter
->dos
.nebr_lba
) {
348 disk_read_sectors(&iter
->di
, iter
->dos
.nebr_lba
, 1))) {
349 error("Couldn't load EBR.");
350 iter
->status
= PI_ERRLOAD
;
354 /* check sanity of loaded data */
355 if (notsane_logical(iter
) || notsane_extended(iter
)) {
356 iter
->status
= PI_INSANE
;
360 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
;
362 iter
->dos
.cebr_lba
= iter
->dos
.nebr_lba
;
363 iter
->dos
.cebr_siz
= iter
->dos
.nebr_siz
;
365 /* setup next frame values */
367 iter
->dos
.nebr_lba
= iter
->dos
.bebr_lba
+ dp
[1].start_lba
;
368 iter
->dos
.nebr_siz
= dp
[1].length
;
370 iter
->dos
.nebr_lba
= 0;
371 iter
->dos
.nebr_siz
= 0;
375 iter
->dos
.logskipcnt
++;
377 if (dp
[0].ostype
|| (iter
->flags
& PIF_STEPALL
)) {
378 *lba
= dp
[0].start_lba
? iter
->dos
.cebr_lba
+ dp
[0].start_lba
: 0;
383 * This way it's possible to continue, if some crazy soft left a "hole"
384 * - EBR with a valid extended partition without a logical one. In
385 * such case, linux will not reserve a number for such hole - so we
386 * don't increase index0. If PIF_STEPALL flag is set, we will never
390 iter
->status
= PI_DONE
;
394 static void gpt_conv_label(struct part_iter
*iter
)
396 const struct disk_gpt_part_entry
*gp
;
397 const int16_t *orig_lab
;
399 gp
= (const struct disk_gpt_part_entry
*)
400 (iter
->data
+ iter
->index0
* iter
->gpt
.pe_size
);
401 orig_lab
= (const int16_t *)gp
->name
;
403 /* caveat: this is very crude conversion */
404 for (int i
= 0; i
< PI_GPTLABSIZE
/2; i
++) {
405 iter
->gpt
.part_label
[i
] = (char)orig_lab
[i
];
407 iter
->gpt
.part_label
[PI_GPTLABSIZE
/2] = 0;
410 static inline int valid_crc(uint32_t crc
, const uint8_t *buf
, unsigned int siz
)
412 return crc
== crc32(crc32(0, NULL
, 0), buf
, siz
);
415 static int valid_crc_hdr(void *buf
)
417 struct disk_gpt_header
*gh
= buf
;
418 uint32_t crc
= gh
->chksum
;
422 valid
= crc
== crc32(crc32(0, NULL
, 0), buf
, gh
->hdr_size
);
427 static int pi_next_(struct part_iter
*iter
)
429 iter
->status
= PI_DONE
;
433 static int pi_dos_next(struct part_iter
*iter
)
435 uint32_t abs_lba
= 0;
436 struct disk_dos_part_entry
*dos_part
= NULL
;
441 /* look for primary partitions */
442 if (iter
->index0
< 4 &&
443 dos_next_mbr(iter
, &abs_lba
, &dos_part
) < 0)
446 /* look for logical partitions */
447 if (iter
->index0
>= 4 &&
448 dos_next_ebr(iter
, &abs_lba
, &dos_part
) < 0)
452 * note special index handling:
453 * in case PIF_STEPALL is set - this makes the index consistent with
454 * non-PIF_STEPALL iterators
457 if (!dos_part
->ostype
)
460 iter
->index
= iter
->index0
+ 1 - iter
->dos
.logskipcnt
;
461 iter
->abs_lba
= abs_lba
;
462 iter
->length
= dos_part
->length
;
463 iter
->record
= (char *)dos_part
;
466 disk_dos_part_dump(dos_part
);
472 static int pi_gpt_next(struct part_iter
*iter
)
474 const struct disk_gpt_part_entry
*gpt_part
= NULL
;
479 while (++iter
->index0
< iter
->gpt
.pe_count
) {
480 gpt_part
= (const struct disk_gpt_part_entry
*)
481 (iter
->data
+ iter
->index0
* iter
->gpt
.pe_size
);
483 if (notsane_gpt(iter
)) {
484 iter
->status
= PI_INSANE
;
488 if (!guid_is0(&gpt_part
->type
) || (iter
->flags
& PIF_STEPALL
))
491 /* no more partitions ? */
492 if (iter
->index0
== iter
->gpt
.pe_count
) {
493 iter
->status
= PI_DONE
;
496 /* gpt_part is guaranteed to be valid here */
497 iter
->index
= iter
->index0
+ 1;
498 iter
->abs_lba
= gpt_part
->lba_first
;
499 iter
->length
= gpt_part
->lba_last
- gpt_part
->lba_first
+ 1;
500 iter
->record
= (char *)gpt_part
;
501 memcpy(&iter
->gpt
.part_guid
, &gpt_part
->uid
, sizeof(struct guid
));
502 gpt_conv_label(iter
);
505 disk_gpt_part_dump(gpt_part
);
511 static struct part_iter
*pi_alloc(void)
513 struct part_iter
*iter
;
514 if (!(iter
= malloc(sizeof *iter
)))
517 memset(iter
, 0, sizeof *iter
);
521 /* pi_del() - delete iterator */
522 void pi_del(struct part_iter
**_iter
)
524 if(!_iter
|| !*_iter
)
531 static void try_gpt_we(const char *str
, int sec
)
539 static struct disk_gpt_header
*try_gpt_hdr(const struct disk_info
*di
, int sec
)
541 const char *desc
= sec
? "backup" : "primary";
542 uint64_t gpt_cur
= sec
? di
->lbacnt
- 1 : 1;
543 struct disk_gpt_header
*gpth
;
546 gpth
= disk_read_sectors(di
, gpt_cur
, 1);
548 sprintf(errbuf
, "Unable to read %s GPT header.", desc
);
549 try_gpt_we(errbuf
, sec
);
552 if(!valid_crc_hdr(gpth
)) {
553 sprintf(errbuf
, "Invalid checksum of %s GPT header.", desc
);
554 try_gpt_we(errbuf
, sec
);
561 static struct disk_gpt_part_entry
*try_gpt_list(const struct disk_info
*di
, const struct disk_gpt_header
*gpth
, int alt
)
563 int pri
= gpth
->lba_cur
< gpth
->lba_alt
;
564 const char *desc
= alt
? "alternative" : "main";
565 struct disk_gpt_part_entry
*gptl
;
567 uint64_t gpt_lsiz
; /* size of GPT partition list in bytes */
568 uint64_t gpt_lcnt
; /* size of GPT partition in sectors */
569 uint64_t gpt_loff
; /* offset to GPT partition list in sectors */
571 gpt_lsiz
= (uint64_t)gpth
->part_size
* gpth
->part_count
;
572 gpt_lcnt
= (gpt_lsiz
+ di
->bps
- 1) / di
->bps
;
574 /* prefer header value for partition table if not asking for alternative */
575 gpt_loff
= gpth
->lba_table
;
577 /* try to read alternative, we have to calculate its position */
579 gpt_loff
= gpth
->lba_alt
+ 1;
581 gpt_loff
= gpth
->lba_alt
- gpt_lcnt
;
584 gptl
= disk_read_sectors(di
, gpt_loff
, gpt_lcnt
);
586 sprintf(errbuf
, "Unable to read %s GPT partition list.", desc
);
587 try_gpt_we(errbuf
, alt
);
590 if (!valid_crc(gpth
->table_chksum
, (const uint8_t *)gptl
, gpt_lsiz
)) {
591 sprintf(errbuf
, "Invalid checksum of %s GPT partition list.", desc
);
592 try_gpt_we(errbuf
, alt
);
599 static int notsane_gpt_hdr(const struct disk_info
*di
, const struct disk_gpt_header
*gpth
, int flags
)
601 uint64_t gpt_loff
; /* offset to GPT partition list in sectors */
602 uint64_t gpt_lsiz
; /* size of GPT partition list in bytes */
603 uint64_t gpt_lcnt
; /* size of GPT partition in sectors */
605 if (!(flags
& PIF_STRICT
))
608 gpt_loff
= gpth
->lba_table
;
609 gpt_lsiz
= (uint64_t)gpth
->part_size
* gpth
->part_count
;
610 gpt_lcnt
= (gpt_lsiz
+ di
->bps
- 1) / di
->bps
;
613 * disk_read_sectors allows reading of max 255 sectors, so we use
614 * it as a sanity check base. EFI doesn't specify max (AFAIK).
616 if (gpt_loff
< 2 || !gpt_lsiz
|| gpt_lcnt
> 255u ||
617 gpth
->lba_first_usable
> gpth
->lba_last_usable
||
618 !sane(gpt_loff
, gpt_lcnt
) ||
619 gpt_loff
+ gpt_lcnt
> gpth
->lba_first_usable
||
620 !sane(gpth
->lba_last_usable
, gpt_lcnt
) ||
621 gpth
->lba_last_usable
+ gpt_lcnt
>= gpth
->lba_alt
||
622 ((flags
& PIF_STRICTER
) && (gpth
->lba_alt
>= di
->lbacnt
)) ||
623 gpth
->part_size
< sizeof(struct disk_gpt_part_entry
))
629 /* pi_begin() - validate and and get proper iterator for a disk described by di */
630 struct part_iter
*pi_begin(const struct disk_info
*di
, int flags
)
632 int isgpt
= 0, ret
= -1;
633 struct part_iter
*iter
;
634 struct disk_dos_mbr
*mbr
= NULL
;
635 struct disk_gpt_header
*gpth
= NULL
;
636 struct disk_gpt_part_entry
*gptl
= NULL
;
638 /* Preallocate iterator */
639 if (!(iter
= pi_alloc()))
643 if (!(mbr
= disk_read_sectors(di
, 0, 1))) {
644 error("Unable to read the first disk sector.");
648 /* Check for MBR magic */
649 if (mbr
->sig
!= disk_mbr_sig_magic
) {
650 warn("No MBR magic, treating disk as raw.");
652 ret
= pi_ctor(iter
, di
, flags
);
656 /* Check for GPT protective MBR */
657 for (size_t i
= 0; i
< 4; i
++)
658 isgpt
|= (mbr
->table
[i
].ostype
== 0xEE);
659 isgpt
= isgpt
&& !(flags
& PIF_PREFMBR
);
661 /* Try to read GPT header */
663 gpth
= try_gpt_hdr(di
, 0);
666 * this read might fail if bios reports different disk size (different vm/pc)
667 * not much we can do here to avoid it
669 gpth
= try_gpt_hdr(di
, 1);
674 if (gpth
&& gpth
->rev
.uint32
== 0x00010000 &&
675 !memcmp(gpth
->sig
, disk_gpt_sig_magic
, sizeof gpth
->sig
)) {
676 /* looks like GPT v1.0 */
678 dprintf("Looks like a GPT v1.0 disk.\n");
679 disk_gpt_header_dump(gpth
);
681 if (notsane_gpt_hdr(di
, gpth
, flags
)) {
682 error("GPT header values are corrupted.");
686 gptl
= try_gpt_list(di
, gpth
, 0);
688 gptl
= try_gpt_list(di
, gpth
, 1);
693 ret
= pi_gpt_ctor(iter
, di
, flags
, gpth
, gptl
);
696 ret
= pi_dos_ctor(iter
, di
, flags
, mbr
);
710 /* vim: set ts=8 sts=4 sw=4 noet: */