summaryrefslogtreecommitdiff
path: root/sys/arch/amd64/stand/efiboot/efidev.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2016-01-03 15:01:32 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2016-01-03 15:01:32 +0000
commit1a400ebf5fa9c7437436ed5b4cc4fb66ddd699d8 (patch)
tree69baa9d4f44d2bd12092a0cd22d511abe10f68a1 /sys/arch/amd64/stand/efiboot/efidev.c
parent5a831ceb7cf6670aba9976bde23f2921d54ffa26 (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/amd64/stand/efiboot/efidev.c')
-rw-r--r--sys/arch/amd64/stand/efiboot/efidev.c42
1 files changed, 23 insertions, 19 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);
}