diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2016-01-03 15:01:32 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2016-01-03 15:01:32 +0000 |
commit | 1a400ebf5fa9c7437436ed5b4cc4fb66ddd699d8 (patch) | |
tree | 69baa9d4f44d2bd12092a0cd22d511abe10f68a1 /sys/arch | |
parent | 5a831ceb7cf6670aba9976bde23f2921d54ffa26 (diff) |
Don't need two 16K static buffers to checksum the GPT entries and find the
OpenBSD partition. Just one 128-byte stack copy of a single entry.
Problems with EFI installs involving many disks reported by and fix
tested by Thomas Bohl.
Stefan Kempf pointed finger of suspicion at the addition of the 2nd
16K static buffer for softraid GPT and suggested/reviewed several
versions of the diff.
Tweaked and ok jsing@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/amd64/stand/efiboot/efidev.c | 42 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/softraid.c | 42 |
2 files changed, 47 insertions, 37 deletions
diff --git a/sys/arch/amd64/stand/efiboot/efidev.c b/sys/arch/amd64/stand/efiboot/efidev.c index 62dd84b7f11..e6bd1014305 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.14 2015/12/24 21:37:25 krw Exp $ */ +/* $OpenBSD: efidev.c,v 1.15 2016/01/03 15:01:31 krw Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -292,14 +292,14 @@ findopenbsd_gpt(efi_diskinfo_t ed, const char **err) { EFI_STATUS status; struct gpt_header gh; - int i, part; + int i, part, found; uint64_t lba; uint32_t orig_csum, new_csum; uint32_t ghsize, ghpartsize, ghpartnum, ghpartspersec; + uint32_t gpsectors; const char openbsd_uuid_code[] = GPT_UUID_OPENBSD; + struct gpt_partition gp; static struct uuid *openbsd_uuid = NULL, openbsd_uuid_space; - static struct gpt_partition - gp[NGPTPARTITIONS]; static u_char buf[4096]; /* Prepare OpenBSD UUID */ @@ -363,28 +363,32 @@ findopenbsd_gpt(efi_diskinfo_t ed, const char **err) ghpartsize = letoh32(gh.gh_part_size); ghpartspersec = ed->blkio->Media->BlockSize / ghpartsize; ghpartnum = letoh32(gh.gh_part_num); - for (i = 0; i < (ghpartnum + ghpartspersec - 1) / ghpartspersec; - i++, lba++) { + gpsectors = (ghpartnum + ghpartspersec - 1) / ghpartspersec; + new_csum = crc32(0L, Z_NULL, 0); + found = 0; + for (i = 0; i < gpsectors; i++, lba++) { status = efid_io(F_READ, ed, EFI_SECTOBLK(ed, lba), EFI_BLKSPERSEC(ed), buf); if (EFI_ERROR(status)) { *err = "Disk I/O Error"; return (-1); } - memcpy(gp + i * ghpartspersec, buf, - ghpartspersec * sizeof(struct gpt_partition)); - } - new_csum = crc32(0, (unsigned char *)&gp, ghpartnum * ghpartsize); - if (new_csum != letoh32(gh.gh_part_csum)) { - *err = "bad GPT partitions checksum\n"; - return (-1); - } - - for (part = 0; part < ghpartnum; part++) { - if (memcmp(&gp[part].gp_type, openbsd_uuid, - sizeof(struct uuid)) == 0) - return letoh64(gp[part].gp_lba_start); + for (part = 0; part < ghpartspersec; part++) { + if (ghpartnum == 0) + break; + new_csum = crc32(new_csum, buf + part * sizeof(gp), + sizeof(gp)); + ghpartnum--; + if (found) + continue; + memcpy(&gp, buf + part * sizeof(gp), sizeof(gp)); + if (memcmp(&gp.gp_type, openbsd_uuid, + sizeof(struct uuid)) == 0) + found = 1; + } } + if (found && new_csum == letoh32(gh.gh_part_csum)) + return letoh64(gp.gp_lba_start); return (-1); } diff --git a/sys/arch/amd64/stand/libsa/softraid.c b/sys/arch/amd64/stand/libsa/softraid.c index d10b514e3c4..747bfda0c29 100644 --- a/sys/arch/amd64/stand/libsa/softraid.c +++ b/sys/arch/amd64/stand/libsa/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.21 2015/12/24 21:37:25 krw Exp $ */ +/* $OpenBSD: softraid.c,v 1.22 2016/01/03 15:01:31 krw Exp $ */ /* * Copyright (c) 2012 Joel Sing <jsing@openbsd.org> @@ -438,15 +438,15 @@ static uint64_t findopenbsd_gpt(struct sr_boot_volume *bv) { struct gpt_header gh; - int i, part; + int i, part, found; uint64_t lba; uint32_t orig_csum, new_csum; uint32_t ghsize, ghpartsize, ghpartnum, ghpartspersec; + uint32_t gpsectors; const char openbsd_uuid_code[] = GPT_UUID_OPENBSD; + struct gpt_partition gp; static struct uuid *openbsd_uuid = NULL, openbsd_uuid_space; - static struct gpt_partition - gp[NGPTPARTITIONS]; - static u_char buf[4096]; + static u_char buf[DEV_BSIZE]; /* Prepare OpenBSD UUID */ if (openbsd_uuid == NULL) { @@ -491,21 +491,27 @@ findopenbsd_gpt(struct sr_boot_volume *bv) ghpartsize = letoh32(gh.gh_part_size); ghpartspersec = DEV_BSIZE / ghpartsize; ghpartnum = letoh32(gh.gh_part_num); - for (i = 0; i < (ghpartnum + ghpartspersec - 1) / ghpartspersec; - i++, lba++) { + gpsectors = (ghpartnum + ghpartspersec - 1) / ghpartspersec; + new_csum = crc32(0L, Z_NULL, 0); + found = 0; + for (i = 0; i < gpsectors; i++, lba++) { sr_strategy(bv, F_READ, lba, DEV_BSIZE, buf, NULL); - memcpy(gp + i * ghpartspersec, buf, - ghpartspersec * sizeof(struct gpt_partition)); - } - new_csum = crc32(0, (unsigned char *)&gp, ghpartnum * ghpartsize); - if (new_csum != letoh32(gh.gh_part_csum)) - return (-1); - - for (part = 0; part < ghpartnum; part++) { - if (memcmp(&gp[part].gp_type, openbsd_uuid, - sizeof(struct uuid)) == 0) - return letoh64(gp[part].gp_lba_start); + for (part = 0; part < ghpartspersec; part++) { + if (ghpartnum == 0) + break; + new_csum = crc32(new_csum, buf + part * sizeof(gp), + sizeof(gp)); + ghpartnum--; + if (found) + continue; + memcpy(&gp, buf + part * sizeof(gp), sizeof(gp)); + if (memcmp(&gp.gp_type, openbsd_uuid, + sizeof(struct uuid)) == 0) + found = 1; + } } + if (found && new_csum == letoh32(gh.gh_part_csum)) + return letoh64(gp.gp_lba_start); return (-1); } |