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-2015 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_gpth(struct disk_gpt_header
*gh
, int flags
)
419 if (!(flags
& PIF_GPTHCRC
))
424 crcc
= crc32(crc32(0, NULL
, 0), (const uint8_t *)gh
, gh
->hdr_size
);
429 static int valid_crc_gptl(const struct disk_gpt_header
*gh
, const struct disk_gpt_part_entry
*gl
, int flags
)
433 if (!(flags
& PIF_GPTLCRC
))
436 crcc
= crc32(crc32(0, NULL
, 0), (const uint8_t *)gl
, gh
->part_size
* gh
->part_count
);
437 return gh
->table_chksum
== crcc
;
440 static int pi_next_(struct part_iter
*iter
)
442 iter
->status
= PI_DONE
;
446 static int pi_dos_next(struct part_iter
*iter
)
448 uint32_t abs_lba
= 0;
449 struct disk_dos_part_entry
*dos_part
= NULL
;
454 /* look for primary partitions */
455 if (iter
->index0
< 4 &&
456 dos_next_mbr(iter
, &abs_lba
, &dos_part
) < 0)
459 /* look for logical partitions */
460 if (iter
->index0
>= 4 &&
461 dos_next_ebr(iter
, &abs_lba
, &dos_part
) < 0)
465 * note special index handling:
466 * in case PIF_STEPALL is set - this makes the index consistent with
467 * non-PIF_STEPALL iterators
470 if (!dos_part
->ostype
)
473 iter
->index
= iter
->index0
+ 1 - iter
->dos
.logskipcnt
;
474 iter
->abs_lba
= abs_lba
;
475 iter
->length
= dos_part
->length
;
476 iter
->record
= (char *)dos_part
;
479 disk_dos_part_dump(dos_part
);
485 static int pi_gpt_next(struct part_iter
*iter
)
487 const struct disk_gpt_part_entry
*gpt_part
= NULL
;
492 while (++iter
->index0
< iter
->gpt
.pe_count
) {
493 gpt_part
= (const struct disk_gpt_part_entry
*)
494 (iter
->data
+ iter
->index0
* iter
->gpt
.pe_size
);
496 if (notsane_gpt(iter
)) {
497 iter
->status
= PI_INSANE
;
501 if (!guid_is0(&gpt_part
->type
) || (iter
->flags
& PIF_STEPALL
))
504 /* no more partitions ? */
505 if (iter
->index0
== iter
->gpt
.pe_count
) {
506 iter
->status
= PI_DONE
;
509 /* gpt_part is guaranteed to be valid here */
510 iter
->index
= iter
->index0
+ 1;
511 iter
->abs_lba
= gpt_part
->lba_first
;
512 iter
->length
= gpt_part
->lba_last
- gpt_part
->lba_first
+ 1;
513 iter
->record
= (char *)gpt_part
;
514 memcpy(&iter
->gpt
.part_guid
, &gpt_part
->uid
, sizeof(struct guid
));
515 gpt_conv_label(iter
);
518 disk_gpt_part_dump(gpt_part
);
524 static struct part_iter
*pi_alloc(void)
526 struct part_iter
*iter
;
527 if (!(iter
= malloc(sizeof *iter
)))
530 memset(iter
, 0, sizeof *iter
);
534 /* pi_del() - delete iterator */
535 void pi_del(struct part_iter
**_iter
)
537 if(!_iter
|| !*_iter
)
544 static int notsane_gpt_hdr(const struct disk_info
*di
, const struct disk_gpt_header
*gpth
, int flags
)
546 uint64_t gpt_loff
; /* offset to GPT partition list in sectors */
547 uint64_t gpt_lsiz
; /* size of GPT partition list in bytes */
548 uint64_t gpt_lcnt
; /* size of GPT partition in sectors */
549 uint64_t gpt_sec
; /* secondary gpt header */
551 if (!(flags
& PIF_STRICT
))
554 if (gpth
->lba_alt
< gpth
->lba_cur
)
555 gpt_sec
= gpth
->lba_cur
;
557 gpt_sec
= gpth
->lba_alt
;
558 gpt_loff
= gpth
->lba_table
;
559 gpt_lsiz
= (uint64_t)gpth
->part_size
* gpth
->part_count
;
560 gpt_lcnt
= (gpt_lsiz
+ di
->bps
- 1) / di
->bps
;
563 * disk_read_sectors allows reading of max 255 sectors, so we use
564 * it as a sanity check base. EFI doesn't specify max (AFAIK).
566 if (gpt_loff
< 2 || !gpt_lsiz
|| gpt_lcnt
> 255u ||
567 gpth
->lba_first_usable
> gpth
->lba_last_usable
||
568 !sane(gpt_loff
, gpt_lcnt
) ||
569 (gpt_loff
+ gpt_lcnt
> gpth
->lba_first_usable
&& gpt_loff
<= gpth
->lba_last_usable
) ||
570 gpt_loff
+ gpt_lcnt
> gpt_sec
||
571 ((flags
& PIF_STRICTER
) && (gpt_sec
>= di
->lbacnt
)) ||
572 gpth
->part_size
< sizeof(struct disk_gpt_part_entry
))
578 static void try_gpt_we(const char *str
, int sec
)
586 static struct disk_gpt_header
*try_gpt_hdr(const struct disk_info
*di
, int sec
, int flags
)
588 const char *desc
= sec
? "backup" : "primary";
589 uint64_t gpt_cur
= sec
? di
->lbacnt
- 1 : 1;
590 struct disk_gpt_header
*gpth
;
593 gpth
= disk_read_sectors(di
, gpt_cur
, 1);
595 sprintf(errbuf
, "Unable to read %s GPT header.", desc
);
598 if(!valid_crc_gpth(gpth
, flags
)) {
599 sprintf(errbuf
, "Invalid checksum of %s GPT header.", desc
);
602 if(notsane_gpt_hdr(di
, gpth
, flags
)) {
603 sprintf(errbuf
, "Checksum of %s GPT header is valid, but values fail sanity checks.", desc
);
608 try_gpt_we(errbuf
, sec
);
613 static struct disk_gpt_part_entry
*try_gpt_list(const struct disk_info
*di
, const struct disk_gpt_header
*gpth
, int alt
, int flags
)
615 int pri
= gpth
->lba_cur
< gpth
->lba_alt
;
616 const char *desc
= alt
? "alternative" : "main";
617 struct disk_gpt_part_entry
*gptl
;
619 uint32_t gpt_lcnt
; /* size of GPT partition in sectors */
620 uint64_t gpt_loff
; /* offset to GPT partition list in sectors */
622 gpt_lcnt
= (gpth
->part_size
* gpth
->part_count
+ di
->bps
- 1) / di
->bps
;
624 /* prefer header value for partition table if not asking for alternative */
625 gpt_loff
= gpth
->lba_table
;
627 /* try to read alternative, we have to calculate its position */
629 gpt_loff
= gpth
->lba_alt
+ 1;
631 gpt_loff
= gpth
->lba_alt
- gpt_lcnt
;
634 gptl
= disk_read_sectors(di
, gpt_loff
, gpt_lcnt
);
636 sprintf(errbuf
, "Unable to read %s GPT partition list.", desc
);
639 if (!valid_crc_gptl(gpth
, gptl
, flags
)) {
640 sprintf(errbuf
, "Invalid checksum of %s GPT partition list.", desc
);
645 try_gpt_we(errbuf
, alt
);
650 /* pi_begin() - validate and and get proper iterator for a disk described by di */
651 struct part_iter
*pi_begin(const struct disk_info
*di
, int flags
)
653 int isgpt
= 0, ret
= -1;
654 struct part_iter
*iter
;
655 struct disk_dos_mbr
*mbr
= NULL
;
656 struct disk_gpt_header
*gpth
= NULL
;
657 struct disk_gpt_part_entry
*gptl
= NULL
;
659 /* Preallocate iterator */
660 if (!(iter
= pi_alloc()))
664 if (!(mbr
= disk_read_sectors(di
, 0, 1))) {
665 error("Unable to read the first disk sector.");
669 /* Check for MBR magic */
670 if (mbr
->sig
!= disk_mbr_sig_magic
) {
671 warn("No MBR magic, treating disk as raw.");
673 ret
= pi_ctor(iter
, di
, flags
);
677 /* Check for GPT protective MBR */
678 for (size_t i
= 0; i
< 4; i
++)
679 isgpt
|= (mbr
->table
[i
].ostype
== 0xEE);
680 isgpt
= isgpt
&& !(flags
& PIF_PREFMBR
);
682 /* Try to read GPT header */
684 gpth
= try_gpt_hdr(di
, 0, flags
);
687 * this read might fail if bios reports different disk size (different vm/pc)
688 * not much we can do here to avoid it
690 gpth
= try_gpt_hdr(di
, 1, flags
);
695 if (gpth
&& gpth
->rev
.uint32
== 0x00010000 &&
696 !memcmp(gpth
->sig
, disk_gpt_sig_magic
, sizeof gpth
->sig
)) {
697 /* looks like GPT v1.0 */
699 dprintf("Looks like a GPT v1.0 disk.\n");
700 disk_gpt_header_dump(gpth
);
702 gptl
= try_gpt_list(di
, gpth
, 0, flags
);
704 gptl
= try_gpt_list(di
, gpth
, 1, flags
);
709 ret
= pi_gpt_ctor(iter
, di
, flags
, gpth
, gptl
);
712 ret
= pi_dos_ctor(iter
, di
, flags
, mbr
);
726 /* vim: set ts=8 sts=4 sw=4 noet: */