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>
47 #define ost_is_ext(type) ((type) == 0x05 || (type) == 0x0F || (type) == 0x85)
48 #define ost_is_nondata(type) (ost_is_ext(type) || (type) == 0x00)
49 #define sane(s,l) ((s)+(l) > (s))
53 static int iter_ctor(struct part_iter
*, va_list *);
54 static int iter_dos_ctor(struct part_iter
*, va_list *);
55 static int iter_gpt_ctor(struct part_iter
*, va_list *);
56 static void iter_dtor(struct part_iter
*);
57 static struct part_iter
*pi_dos_next(struct part_iter
*);
58 static struct part_iter
*pi_gpt_next(struct part_iter
*);
59 static struct part_iter
*pi_raw_next(struct part_iter
*);
61 static struct itertype types
[] = {
63 .ctor
= &iter_dos_ctor
,
67 .ctor
= &iter_gpt_ctor
,
76 const struct itertype
* const typedos
= types
;
77 const struct itertype
* const typegpt
= types
+1;
78 const struct itertype
* const typeraw
= types
+2;
81 static int inv_type(const void *type
)
83 int i
, cnt
= sizeof(types
)/sizeof(types
[0]);
84 for (i
= 0; i
< cnt
; i
++) {
85 if (type
== types
+ i
)
93 * iter_ctor() - common iterator initialization
94 * @iter: iterator pointer
95 * @args(0): disk_info structure used for disk functions
96 * @args(1): stepall modifier
98 * Second and further arguments are passed as a pointer to va_list
100 static int iter_ctor(struct part_iter
*iter
, va_list *args
)
102 const struct disk_info
*di
= va_arg(*args
, const struct disk_info
*);
103 int stepall
= va_arg(*args
, int);
110 memcpy(&iter
->di
, di
, sizeof(struct disk_info
));
111 iter
->stepall
= stepall
;
113 iter
->length
= di
->lbacnt
;
119 * iter_dtor() - common iterator cleanup
120 * @iter: iterator pointer
123 static void iter_dtor(struct part_iter
*iter
)
129 * iter_dos_ctor() - MBR/EBR iterator specific initialization
130 * @iter: iterator pointer
131 * @args(0): disk_info structure used for disk functions
132 * @args(1): pointer to buffer with loaded valid MBR
134 * Second and further arguments are passed as a pointer to va_list.
135 * This function only makes rudimentary checks. If user uses
136 * pi_new(), he/she is responsible for doing proper sanity checks.
138 static int iter_dos_ctor(struct part_iter
*iter
, va_list *args
)
140 const struct disk_dos_mbr
*mbr
;
143 if (iter_ctor(iter
, args
))
146 mbr
= va_arg(*args
, const struct disk_dos_mbr
*);
153 if (!(iter
->data
= malloc(sizeof(struct disk_dos_mbr
))))
156 memcpy(iter
->data
, mbr
, sizeof(struct disk_dos_mbr
));
158 iter
->sub
.dos
.bebr_index0
= -1;
159 iter
->sub
.dos
.disk_sig
= mbr
->disk_sig
;
163 iter
->type
->dtor(iter
);
168 * iter_gpt_ctor() - GPT iterator specific initialization
169 * @iter: iterator pointer
170 * @args(0): ptr to disk_info structure
171 * @args(1): ptr to buffer with GPT header
172 * @args(2): ptr to buffer with GPT partition list
174 * Second and further arguments are passed as a pointer to va_list.
175 * This function only makes rudimentary checks. If user uses
176 * pi_new(), he/she is responsible for doing proper sanity checks.
178 static int iter_gpt_ctor(struct part_iter
*iter
, va_list *args
)
181 const struct disk_gpt_header
*gpth
;
182 const struct disk_gpt_part_entry
*gptl
;
185 if (iter_ctor(iter
, args
))
188 gpth
= va_arg(*args
, const struct disk_gpt_header
*);
189 gptl
= va_arg(*args
, const struct disk_gpt_part_entry
*);
196 siz
= (uint64_t)gpth
->part_count
* gpth
->part_size
;
199 if (!siz
|| (siz
+ iter
->di
.bps
- 1) / iter
->di
.bps
> 255u ||
200 gpth
->part_size
< sizeof(struct disk_gpt_part_entry
)) {
205 if (!(iter
->data
= malloc((size_t)siz
)))
208 memcpy(iter
->data
, gptl
, (size_t)siz
);
210 iter
->sub
.gpt
.pe_count
= (int)gpth
->part_count
;
211 iter
->sub
.gpt
.pe_size
= (int)gpth
->part_size
;
212 iter
->sub
.gpt
.ufirst
= gpth
->lba_first_usable
;
213 iter
->sub
.gpt
.ulast
= gpth
->lba_last_usable
;
215 memcpy(&iter
->sub
.gpt
.disk_guid
, &gpth
->disk_guid
, sizeof(struct guid
));
219 iter
->type
->dtor(iter
);
223 /* Logical partition must be sane, meaning:
224 * - must be data or empty
225 * - must have non-0 start and length
226 * - values must not wrap around 32bit
227 * - must be inside current EBR frame
230 static int notsane_logical(const struct part_iter
*iter
)
232 const struct disk_dos_part_entry
*dp
;
235 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
;
240 if (ost_is_ext(dp
[0].ostype
)) {
241 error("1st EBR entry must be data or empty.\n");
245 end_log
= dp
[0].start_lba
+ dp
[0].length
;
247 if (!dp
[0].start_lba
||
249 !sane(dp
[0].start_lba
, dp
[0].length
) ||
250 end_log
> iter
->sub
.dos
.ebr_size
) {
252 error("Insane logical partition.\n");
259 /* Extended partition must be sane, meaning:
260 * - must be extended or empty
261 * - must have non-0 start and length
262 * - values must not wrap around 32bit
263 * - must be inside base EBR frame
266 static int notsane_extended(const struct part_iter
*iter
)
268 const struct disk_dos_part_entry
*dp
;
271 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
;
276 if (!ost_is_nondata(dp
[1].ostype
)) {
277 error("2nd EBR entry must be extended or empty.\n");
281 end_ebr
= dp
[1].start_lba
+ dp
[1].length
;
283 if (!dp
[1].start_lba
||
285 !sane(dp
[1].start_lba
, dp
[1].length
) ||
286 end_ebr
> iter
->sub
.dos
.bebr_size
) {
288 error("Insane extended partition.\n");
295 /* Primary partition must be sane, meaning:
296 * - must have non-0 start and length
297 * - values must not wrap around 32bit
300 static int notsane_primary(const struct part_iter
*iter
)
302 const struct disk_dos_part_entry
*dp
;
303 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
+ iter
->index0
;
308 if (!dp
->start_lba
||
310 !sane(dp
->start_lba
, dp
->length
) ||
311 dp
->start_lba
+ dp
->length
> iter
->di
.lbacnt
) {
312 error("Insane primary (MBR) partition.\n");
319 static int notsane_gpt(const struct part_iter
*iter
)
321 const struct disk_gpt_part_entry
*gp
;
322 gp
= (const struct disk_gpt_part_entry
*)
323 (iter
->data
+ iter
->index0
* iter
->sub
.gpt
.pe_size
);
325 if (guid_is0(&gp
->type
))
328 if (gp
->lba_first
< iter
->sub
.gpt
.ufirst
||
329 gp
->lba_last
> iter
->sub
.gpt
.ulast
) {
330 error("Insane GPT partition.\n");
337 static int pi_dos_next_mbr(struct part_iter
*iter
, uint32_t *lba
,
338 struct disk_dos_part_entry
**_dp
)
340 struct disk_dos_part_entry
*dp
;
342 while (++iter
->index0
< 4) {
343 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
+ iter
->index0
;
345 if (notsane_primary(iter
)) {
346 iter
->status
= PI_INSANE
;
350 if (ost_is_ext(dp
->ostype
)) {
351 if (iter
->sub
.dos
.bebr_index0
>= 0) {
352 error("You have more than 1 extended partition.\n");
353 iter
->status
= PI_INSANE
;
356 /* record base EBR index */
357 iter
->sub
.dos
.bebr_index0
= iter
->index0
;
359 if (!ost_is_nondata(dp
->ostype
) || iter
->stepall
) {
360 *lba
= dp
->start_lba
;
371 static int prep_base_ebr(struct part_iter
*iter
)
373 struct disk_dos_part_entry
*dp
;
375 if (iter
->sub
.dos
.bebr_index0
< 0) /* if we don't have base extended partition at all */
377 else if (!iter
->sub
.dos
.bebr_start
) { /* if not initialized yet */
378 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
+ iter
->sub
.dos
.bebr_index0
;
380 iter
->sub
.dos
.bebr_start
= dp
->start_lba
;
381 iter
->sub
.dos
.bebr_size
= dp
->length
;
383 iter
->sub
.dos
.ebr_start
= 0;
384 iter
->sub
.dos
.ebr_size
= iter
->sub
.dos
.bebr_size
;
386 iter
->sub
.dos
.cebr_lba
= 0;
387 iter
->sub
.dos
.nebr_lba
= iter
->sub
.dos
.bebr_start
;
394 static int pi_dos_next_ebr(struct part_iter
*iter
, uint32_t *lba
,
395 struct disk_dos_part_entry
**_dp
)
397 struct disk_dos_part_entry
*dp
;
399 if (prep_base_ebr(iter
)) {
400 iter
->status
= PI_DONE
;
404 while (++iter
->index0
< 1024 && iter
->sub
.dos
.nebr_lba
) {
407 disk_read_sectors(&iter
->di
, iter
->sub
.dos
.nebr_lba
, 1))) {
408 error("Couldn't load EBR.\n");
409 iter
->status
= PI_ERRLOAD
;
413 if (notsane_logical(iter
) || notsane_extended(iter
)) {
414 iter
->status
= PI_INSANE
;
418 dp
= ((struct disk_dos_mbr
*)iter
->data
)->table
;
420 iter
->sub
.dos
.cebr_lba
= iter
->sub
.dos
.nebr_lba
;
422 /* setup next frame values */
424 iter
->sub
.dos
.ebr_start
= dp
[1].start_lba
;
425 iter
->sub
.dos
.ebr_size
= dp
[1].length
;
426 iter
->sub
.dos
.nebr_lba
= iter
->sub
.dos
.bebr_start
+ dp
[1].start_lba
;
428 iter
->sub
.dos
.ebr_start
= 0;
429 iter
->sub
.dos
.ebr_size
= 0;
430 iter
->sub
.dos
.nebr_lba
= 0;
434 iter
->sub
.dos
.skipcnt
++;
436 if (dp
[0].ostype
|| iter
->stepall
) {
437 *lba
= iter
->sub
.dos
.cebr_lba
+ dp
[0].start_lba
;
442 * This way it's possible to continue, if some crazy soft left a "hole"
443 * - EBR with a valid extended partition without a logical one. In
444 * such case, linux will not reserve a number for such hole - so we
445 * don't increase index0. If stepall flag is set, we will never reach
449 iter
->status
= PI_DONE
;
453 static struct part_iter
*pi_dos_next(struct part_iter
*iter
)
455 uint32_t start_lba
= 0;
456 struct disk_dos_part_entry
*dos_part
= NULL
;
461 /* look for primary partitions */
462 if (iter
->index0
< 4 &&
463 pi_dos_next_mbr(iter
, &start_lba
, &dos_part
))
466 /* look for logical partitions */
467 if (iter
->index0
>= 4 &&
468 pi_dos_next_ebr(iter
, &start_lba
, &dos_part
))
472 * note special index handling, if we have stepall set -
473 * this is made to keep index consistent with non-stepall
477 if (iter
->index0
>= 4 && !dos_part
->ostype
)
480 iter
->index
= iter
->index0
- iter
->sub
.dos
.skipcnt
+ 1;
481 iter
->rawindex
= iter
->index0
+ 1;
482 iter
->start_lba
= start_lba
;
483 iter
->length
= dos_part
->length
;
484 iter
->record
= (char *)dos_part
;
487 disk_dos_part_dump(dos_part
);
495 static void gpt_conv_label(struct part_iter
*iter
)
497 const struct disk_gpt_part_entry
*gp
;
498 const int16_t *orig_lab
;
500 gp
= (const struct disk_gpt_part_entry
*)
501 (iter
->data
+ iter
->index0
* iter
->sub
.gpt
.pe_size
);
502 orig_lab
= (const int16_t *)gp
->name
;
504 /* caveat: this is very crude conversion */
505 for (int i
= 0; i
< PI_GPTLABSIZE
/2; i
++) {
506 iter
->sub
.gpt
.part_label
[i
] = (char)orig_lab
[i
];
508 iter
->sub
.gpt
.part_label
[PI_GPTLABSIZE
/2] = 0;
511 static struct part_iter
*pi_gpt_next(struct part_iter
*iter
)
513 const struct disk_gpt_part_entry
*gpt_part
= NULL
;
518 while (++iter
->index0
< iter
->sub
.gpt
.pe_count
) {
519 gpt_part
= (const struct disk_gpt_part_entry
*)
520 (iter
->data
+ iter
->index0
* iter
->sub
.gpt
.pe_size
);
522 if (notsane_gpt(iter
)) {
523 iter
->status
= PI_INSANE
;
527 if (!guid_is0(&gpt_part
->type
) || iter
->stepall
)
530 /* no more partitions ? */
531 if (iter
->index0
== iter
->sub
.gpt
.pe_count
) {
532 iter
->status
= PI_DONE
;
535 /* gpt_part is guaranteed to be valid here */
536 iter
->index
= iter
->index0
+ 1;
537 iter
->rawindex
= iter
->index0
+ 1;
538 iter
->start_lba
= gpt_part
->lba_first
;
539 iter
->length
= gpt_part
->lba_last
- gpt_part
->lba_first
+ 1;
540 iter
->record
= (char *)gpt_part
;
541 memcpy(&iter
->sub
.gpt
.part_guid
, &gpt_part
->uid
, sizeof(struct guid
));
542 gpt_conv_label(iter
);
545 disk_gpt_part_dump(gpt_part
);
553 static struct part_iter
*pi_raw_next(struct part_iter
*iter
)
555 iter
->status
= PI_DONE
;
559 static int check_crc(uint32_t crc_match
, const uint8_t *buf
, unsigned int siz
)
563 crc
= crc32(0, NULL
, 0);
564 crc
= crc32(crc
, buf
, siz
);
566 return crc_match
!= crc
;
569 static int gpt_check_hdr_crc(const struct disk_info
* const diskinfo
, struct disk_gpt_header
**_gh
)
571 struct disk_gpt_header
*gh
= *_gh
;
575 hold_crc32
= gh
->chksum
;
577 if (check_crc(hold_crc32
, (const uint8_t *)gh
, gh
->hdr_size
)) {
578 error("WARNING: Primary GPT header checksum invalid.\n");
579 /* retry with backup */
580 lba_alt
= gh
->lba_alt
;
582 if (!(gh
= *_gh
= disk_read_sectors(diskinfo
, lba_alt
, 1))) {
583 error("Couldn't read backup GPT header.\n");
586 hold_crc32
= gh
->chksum
;
588 if (check_crc(hold_crc32
, (const uint8_t *)gh
, gh
->hdr_size
)) {
589 error("Secondary GPT header checksum invalid.\n");
593 /* restore old checksum */
594 gh
->chksum
= hold_crc32
;
600 * ----------------------------------------------------------------------------
601 * Following functions are for users to call.
602 * ----------------------------------------------------------------------------
606 int pi_next(struct part_iter
**_iter
)
608 struct part_iter
*iter
;
610 if(!_iter
|| !*_iter
)
614 if (inv_type(iter
->type
)) {
615 error("This is not a valid iterator.\n");
619 if ((iter
= iter
->type
->next(iter
))) {
622 return (*_iter
)->status
;
626 * pi_new() - get new iterator
627 * @itertype: iterator type
628 * @...: variable arguments passed to ctors
630 * Variable arguments depend on the type. Please see functions:
631 * iter_gpt_ctor() and iter_dos_ctor() for details.
633 struct part_iter
*pi_new(const struct itertype
*type
, ...)
636 struct part_iter
*iter
= NULL
;
642 if (inv_type(type
)) {
643 error("Unknown iterator requested.\n");
648 if (!(iter
= malloc(sizeof(struct part_iter
)))) {
649 error("Couldn't allocate memory for the iterator.\n");
653 memset(iter
, 0, sizeof(struct part_iter
));
656 if (type
->ctor(iter
, &ap
)) {
658 error("Cannot initialize the iterator.\n");
672 * pi_del() - delete iterator
673 * @iter: iterator double pointer
677 void pi_del(struct part_iter
**_iter
)
679 struct part_iter
*iter
;
681 if(!_iter
|| !*_iter
)
686 if (inv_type(iter
->type
)) {
687 error("This is not a valid iterator.\n");
692 iter
->type
->dtor(iter
);
698 * pi_begin() - check disk, validate, and get proper iterator
699 * @di: diskinfo struct pointer
701 * This function checks the disk for GPT or legacy partition table and allocates
702 * an appropriate iterator.
704 struct part_iter
*pi_begin(const struct disk_info
*di
, int stepall
)
707 struct part_iter
*iter
= NULL
;
708 struct disk_dos_mbr
*mbr
= NULL
;
709 struct disk_gpt_header
*gpth
= NULL
;
710 struct disk_gpt_part_entry
*gptl
= NULL
;
713 if (!(mbr
= disk_read_sectors(di
, 0, 1))) {
714 error("Couldn't read first disk sector.\n");
720 /* Check for MBR magic*/
721 if (mbr
->sig
!= disk_mbr_sig_magic
) {
722 error("No MBR magic.\n");
726 /* Check for GPT protective MBR */
727 if (mbr
->table
[0].ostype
== 0xEE) {
728 if (!(gpth
= disk_read_sectors(di
, 1, 1))) {
729 error("Couldn't read potential GPT header.\n");
734 if (gpth
&& gpth
->rev
.uint32
== 0x00010000 &&
735 !memcmp(gpth
->sig
, disk_gpt_sig_magic
, sizeof(disk_gpt_sig_magic
))) {
736 /* looks like GPT v1.0 */
737 uint64_t gpt_loff
; /* offset to GPT partition list in sectors */
738 uint64_t gpt_lsiz
; /* size of GPT partition list in bytes */
739 uint64_t gpt_lcnt
; /* size of GPT partition in sectors */
741 puts("Looks like a GPT v1.0 disk.");
742 disk_gpt_header_dump(gpth
);
744 /* Verify checksum, fallback to backup, then bail if invalid */
745 if (gpt_check_hdr_crc(di
, &gpth
))
748 gpt_loff
= gpth
->lba_table
;
749 gpt_lsiz
= (uint64_t)gpth
->part_size
* gpth
->part_count
;
750 gpt_lcnt
= (gpt_lsiz
+ di
->bps
- 1) / di
->bps
;
753 * disk_read_sectors allows reading of max 255 sectors, so we use
754 * it as a sanity check base. EFI doesn't specify max (AFAIK).
755 * Apart from that, some extensive sanity checks.
757 if (!gpt_loff
|| !gpt_lsiz
|| gpt_lcnt
> 255u ||
758 gpth
->lba_first_usable
> gpth
->lba_last_usable
||
759 !sane(gpt_loff
, gpt_lcnt
) ||
760 gpt_loff
+ gpt_lcnt
> gpth
->lba_first_usable
||
761 !sane(gpth
->lba_last_usable
, gpt_lcnt
) ||
762 gpth
->lba_last_usable
+ gpt_lcnt
>= gpth
->lba_alt
||
763 gpth
->lba_alt
>= di
->lbacnt
||
764 gpth
->part_size
< sizeof(struct disk_gpt_part_entry
)) {
765 error("Invalid GPT header's values.\n");
768 if (!(gptl
= disk_read_sectors(di
, gpt_loff
, gpt_lcnt
))) {
769 error("Couldn't read GPT partition list.\n");
772 /* Check array checksum(s). */
773 if (check_crc(gpth
->table_chksum
, (const uint8_t *)gptl
, (unsigned int)gpt_lsiz
)) {
774 error("WARNING: GPT partition list checksum invalid, trying backup.\n");
776 /* secondary array directly precedes secondary header */
777 if (!(gptl
= disk_read_sectors(di
, gpth
->lba_alt
- gpt_lcnt
, gpt_lcnt
))) {
778 error("Couldn't read backup GPT partition list.\n");
781 if (check_crc(gpth
->table_chksum
, (const uint8_t *)gptl
, gpt_lsiz
)) {
782 error("Backup GPT partition list checksum invalid.\n");
786 /* allocate iterator and exit */
787 iter
= pi_new(typegpt
, di
, stepall
, gpth
, gptl
);
790 iter
= pi_new(typedos
, di
, stepall
, mbr
);
796 error("WARNING: treating disk as raw.\n");
797 iter
= pi_new(typeraw
, di
, stepall
);
806 /* vim: set ts=8 sts=4 sw=4 noet: */