diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2016-05-01 10:43:06 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2016-05-01 10:43:06 +0000 |
commit | 15b822ae4e408993e5f57005ccd5d2c19ccd5f90 (patch) | |
tree | fa407d6f162b70b750e1eb8eba60072a3955faae /sys/arch/amd64 | |
parent | c224352ed8aa709d2830d558e830a65991b5da6d (diff) |
Shuffle gpt/mbr code around a bit to make it more like other searches
for the disklabel. Tweak a few comments to make it more clear what
is happening. No intentional functional change.
ok yasuoka@
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/stand/efiboot/efidev.c | 99 |
1 files changed, 64 insertions, 35 deletions
diff --git a/sys/arch/amd64/stand/efiboot/efidev.c b/sys/arch/amd64/stand/efiboot/efidev.c index 22a6463f80f..64dde530543 100644 --- a/sys/arch/amd64/stand/efiboot/efidev.c +++ b/sys/arch/amd64/stand/efiboot/efidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efidev.c,v 1.16 2016/01/06 02:10:03 krw Exp $ */ +/* $OpenBSD: efidev.c,v 1.17 2016/05/01 10:43:05 krw Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -62,7 +62,7 @@ static EFI_STATUS efid_io(int, efi_diskinfo_t, u_int, int, void *); static int efid_diskio(int, struct diskinfo *, u_int, int, void *); static u_int findopenbsd(efi_diskinfo_t, const char **); -static uint64_t findopenbsd_gpt(efi_diskinfo_t, const char **); +static u_int findopenbsd_gpt(efi_diskinfo_t, const char **); static int gpt_chk_mbr(struct dos_partition *, u_int64_t); void @@ -198,7 +198,15 @@ gpt_chk_mbr(struct dos_partition *dp, u_int64_t dsize) } /* - * Try to read the bsd label on the given BIOS device. + * Try to find the disk address of the first MBR OpenBSD partition. + * + * N.B.: must boot from a partition within first 2^32-1 sectors! + * + * Called only if the MBR on sector 0 is *not* a protective MBR + * and *does* have a valid signature. + * + * We don't check the signatures of EBR's, and they cannot be + * protective MBR's so there is no need to check for that. */ static u_int findopenbsd(efi_diskinfo_t ed, const char **err) @@ -206,7 +214,6 @@ findopenbsd(efi_diskinfo_t ed, const char **err) EFI_STATUS status; struct dos_mbr mbr; struct dos_partition *dp; - uint64_t gptoff; u_int mbroff = DOSBBSECTOR; u_int mbr_eoff = DOSBBSECTOR; /* Offset of MBR extended partition. */ int i, maxebr = DOS_MAXEBR, nextebr; @@ -225,25 +232,6 @@ again: return (-1); } - /* check mbr signature */ - if (mbr.dmbr_sign != DOSMBR_SIGNATURE) { - *err = "bad MBR signature\n"; - return (-1); - } - - /* check for GPT protective MBR. */ - if (mbroff == DOSBBSECTOR && gpt_chk_mbr(mbr.dmbr_parts, - ed->blkio->Media->LastBlock + 1) == 0) { - gptoff = findopenbsd_gpt(ed, err); - if (gptoff > UINT_MAX || EFI_SECTOBLK(ed, gptoff) > UINT_MAX) { - *err = "Paritition LBA > 2**32"; - return (-1); - } - if (gptoff == -1) - return (-1); - return EFI_SECTOBLK(ed, gptoff); - } - /* Search for OpenBSD partition */ nextebr = 0; for (i = 0; i < NDOSPART; i++) { @@ -286,8 +274,15 @@ again: return (-1); } -/* call this only if LBA1 == GPT */ -static uint64_t +/* + * Try to find the disk address of the first GPT OpenBSD partition. + * + * N.B.: must boot from a partition within first 2^32-1 sectors! + * + * Called only if the MBR on sector 0 *is* a protective MBR + * with a valid signature and sector 1 is a valid GPT header. + */ +static u_int findopenbsd_gpt(efi_diskinfo_t ed, const char **err) { EFI_STATUS status; @@ -391,8 +386,15 @@ findopenbsd_gpt(efi_diskinfo_t ed, const char **err) *err = "bad GPT entries checksum\n"; return (-1); } - if (found) - return (letoh64(gp.gp_lba_start)); + if (found) { + lba = letoh64(gp.gp_lba_start); + /* Bootloaders do not current handle addresses > UINT_MAX! */ + if (lba > UINT_MAX || EFI_SECTOBLK(ed, lba) > UINT_MAX) { + *err = "OpenBSD Partition LBA > 2**32 - 1"; + return (-1); + } + return (u_int)lba; + } return (-1); } @@ -401,18 +403,45 @@ const char * efi_getdisklabel(efi_diskinfo_t ed, struct disklabel *label) { u_int start = 0; - char buf[DEV_BSIZE]; + uint8_t buf[DEV_BSIZE]; + struct dos_partition dosparts[NDOSPART]; + EFI_STATUS status; const char *err = NULL; int error; - /* Sanity check */ - /* XXX */ + /* + * Read sector 0. Ensure it has a valid MBR signature. + * + * If it's a protective MBR then try to find the disklabel via + * GPT. If it's not a protective MBR, try to find the disklabel + * via MBR. + */ + memset(buf, 0, sizeof(buf)); + status = efid_io(F_READ, ed, DOSBBSECTOR, 1, buf); + if (EFI_ERROR(status)) + return ("Disk I/O Error"); + + /* Check MBR signature. */ + if (buf[510] != 0x55 || buf[511] != 0xaa) + return ("invalid MBR signature"); + + memcpy(dosparts, buf+DOSPARTOFF, sizeof(dosparts)); - start = findopenbsd(ed, &err); - if (start == (u_int)-1) { - if (err != NULL) - return (err); - return "no OpenBSD partition\n"; + /* check for GPT protective MBR. */ + if (gpt_chk_mbr(dosparts, ed->blkio->Media->LastBlock + 1) == 0) { + start = findopenbsd_gpt(ed, &err); + if (start == (u_int)-1) { + if (err != NULL) + return (err); + return ("no OpenBSD GPT partition"); + } + } else { + start = findopenbsd(ed, &err); + if (start == (u_int)-1) { + if (err != NULL) + return (err); + return "no OpenBSD MBR partition\n"; + } } /* Load BSD disklabel */ |