Module Name: src
Committed By: jmcneill
Date: Thu Nov 1 00:43:38 UTC 2018
Modified Files:
src/sys/stand/efiboot: efiblock.c efiblock.h efiboot.c efifdt.c version
Log Message:
Add GPT support.
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/stand/efiboot/efiblock.c
cvs rdiff -u -r1.2 -r1.3 src/sys/stand/efiboot/efiblock.h
cvs rdiff -u -r1.11 -r1.12 src/sys/stand/efiboot/efiboot.c \
src/sys/stand/efiboot/efifdt.c
cvs rdiff -u -r1.6 -r1.7 src/sys/stand/efiboot/version
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/stand/efiboot/efiblock.c
diff -u src/sys/stand/efiboot/efiblock.c:1.3 src/sys/stand/efiboot/efiblock.c:1.4
--- src/sys/stand/efiboot/efiblock.c:1.3 Fri Sep 14 21:37:03 2018
+++ src/sys/stand/efiboot/efiblock.c Thu Nov 1 00:43:38 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: efiblock.c,v 1.3 2018/09/14 21:37:03 jakllsch Exp $ */
+/* $NetBSD: efiblock.c,v 1.4 2018/11/01 00:43:38 jmcneill Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -31,6 +31,7 @@
#include <sys/param.h>
#include <sys/md5.h>
+#include <sys/uuid.h>
#include "efiboot.h"
#include "efiblock.h"
@@ -192,16 +193,114 @@ efi_block_find_partitions_mbr(struct efi
return 0;
}
+static const struct {
+ struct uuid guid;
+ uint8_t fstype;
+} gpt_guid_to_str[] = {
+ { GPT_ENT_TYPE_NETBSD_FFS, FS_BSDFFS },
+ { GPT_ENT_TYPE_NETBSD_LFS, FS_BSDLFS },
+ { GPT_ENT_TYPE_NETBSD_RAIDFRAME, FS_RAID },
+ { GPT_ENT_TYPE_NETBSD_CCD, FS_CCD },
+ { GPT_ENT_TYPE_NETBSD_CGD, FS_CGD },
+ { GPT_ENT_TYPE_MS_BASIC_DATA, FS_MSDOS }, /* or NTFS? ambiguous */
+};
+
+static int
+efi_block_find_partitions_gpt_entry(struct efi_block_dev *bdev, struct gpt_hdr *hdr, struct gpt_ent *ent, UINT32 index)
+{
+ struct efi_block_part *bpart;
+ uint8_t fstype = FS_UNUSED;
+ struct uuid uuid;
+ int n;
+
+ memcpy(&uuid, ent->ent_type, sizeof(uuid));
+ for (n = 0; n < __arraycount(gpt_guid_to_str); n++)
+ if (memcmp(ent->ent_type, &gpt_guid_to_str[n].guid, sizeof(ent->ent_type)) == 0) {
+ fstype = gpt_guid_to_str[n].fstype;
+ break;
+ }
+ if (fstype == FS_UNUSED)
+ return 0;
+
+ bpart = alloc(sizeof(*bpart));
+ bpart->index = index;
+ bpart->bdev = bdev;
+ bpart->type = EFI_BLOCK_PART_GPT;
+ bpart->gpt.fstype = fstype;
+ bpart->gpt.ent = *ent;
+ memcpy(bpart->hash, ent->ent_guid, sizeof(bpart->hash));
+ TAILQ_INSERT_TAIL(&bdev->partitions, bpart, entries);
+
+ return 0;
+}
+
+static int
+efi_block_find_partitions_gpt(struct efi_block_dev *bdev)
+{
+ struct gpt_hdr hdr;
+ struct gpt_ent ent;
+ EFI_STATUS status;
+ UINT32 sz, entry;
+ uint8_t *buf;
+
+ sz = __MAX(sizeof(hdr), bdev->bio->Media->BlockSize);
+ sz = roundup(sz, bdev->bio->Media->BlockSize);
+ buf = AllocatePool(sz);
+ if (!buf)
+ return ENOMEM;
+
+ status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, GPT_HDR_BLKNO, sz, buf);
+ if (EFI_ERROR(status)) {
+ FreePool(buf);
+ return EIO;
+ }
+ memcpy(&hdr, buf, sizeof(hdr));
+ FreePool(buf);
+
+ if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0)
+ return ENOENT;
+ if (le32toh(hdr.hdr_entsz) < sizeof(ent))
+ return EINVAL;
+
+ sz = __MAX(le32toh(hdr.hdr_entsz) * le32toh(hdr.hdr_entries), bdev->bio->Media->BlockSize);
+ sz = roundup(sz, bdev->bio->Media->BlockSize);
+ buf = AllocatePool(sz);
+ if (!buf)
+ return ENOMEM;
+
+ status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, le64toh(hdr.hdr_lba_table), sz, buf);
+ if (EFI_ERROR(status)) {
+ FreePool(buf);
+ return EIO;
+ }
+
+ for (entry = 0; entry < le32toh(hdr.hdr_entries); entry++) {
+ memcpy(&ent, buf + (entry * le32toh(hdr.hdr_entsz)), sizeof(ent));
+ efi_block_find_partitions_gpt_entry(bdev, &hdr, &ent, entry);
+ }
+
+ FreePool(buf);
+
+ return 0;
+}
+
static int
efi_block_find_partitions(struct efi_block_dev *bdev)
{
- return efi_block_find_partitions_mbr(bdev);
+ int error;
+
+ error = efi_block_find_partitions_gpt(bdev);
+ if (error)
+ error = efi_block_find_partitions_mbr(bdev);
+
+ return error;
}
void
efi_block_probe(void)
{
struct efi_block_dev *bdev;
+ struct efi_block_part *bpart;
EFI_BLOCK_IO *bio;
EFI_STATUS status;
uint16_t devindex = 0;
@@ -234,13 +333,40 @@ efi_block_probe(void)
TAILQ_INIT(&bdev->partitions);
TAILQ_INSERT_TAIL(&efi_block_devs, bdev, entries);
+ efi_block_find_partitions(bdev);
+
if (depth > 0 && efi_device_path_ncmp(efi_bootdp, DevicePathFromHandle(efi_block[n]), depth) == 0) {
- char devname[9];
- snprintf(devname, sizeof(devname), "hd%ua", bdev->index);
- set_default_device(devname);
+ TAILQ_FOREACH(bpart, &bdev->partitions, entries) {
+ uint8_t fstype = FS_UNUSED;
+ switch (bpart->type) {
+ case EFI_BLOCK_PART_DISKLABEL:
+ fstype = bpart->disklabel.part.p_fstype;
+ break;
+ case EFI_BLOCK_PART_GPT:
+ fstype = bpart->gpt.fstype;
+ break;
+ }
+ if (fstype == FS_BSDFFS) {
+ char devname[9];
+ snprintf(devname, sizeof(devname), "hd%u%c", bdev->index, bpart->index + 'a');
+ set_default_device(devname);
+ break;
+ }
+ }
}
+ }
+}
- efi_block_find_partitions(bdev);
+static void
+print_guid(const uint8_t *guid)
+{
+ const int index[] = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ printf("%02x", guid[index[i]]);
+ if (i == 3 || i == 5 || i == 7 || i == 9)
+ printf("-");
}
}
@@ -284,6 +410,27 @@ efi_block_show(void)
printf("%s\n", fstypenames[bpart->disklabel.part.p_fstype]);
break;
+ case EFI_BLOCK_PART_GPT:
+ printf(" hd%u%c ", bdev->index, bpart->index + 'a');
+
+ if (bpart->gpt.ent.ent_name[0] == 0x0000) {
+ printf("\"");
+ print_guid(bpart->gpt.ent.ent_guid);
+ printf("\"");
+ } else {
+ Print(L"\"%s\"", bpart->gpt.ent.ent_name);
+ }
+
+ /* Size in MB */
+ size = (le64toh(bpart->gpt.ent.ent_lba_end) - le64toh(bpart->gpt.ent.ent_lba_start)) * bdev->bio->Media->BlockSize;
+ size /= (1024 * 1024);
+ if (size >= 10000)
+ printf(" (%"PRIu64" GB): ", size / 1024);
+ else
+ printf(" (%"PRIu64" MB): ", size);
+
+ printf("%s\n", fstypenames[bpart->gpt.fstype]);
+ break;
default:
break;
}
@@ -357,6 +504,14 @@ efi_block_strategy(void *devdata, int rw
}
dblk += bpart->disklabel.part.p_offset;
break;
+ case EFI_BLOCK_PART_GPT:
+ if (bpart->bdev->bio->Media->BlockSize != DEV_BSIZE) {
+ printf("%s: unsupported block size %d (expected %d)\n", __func__,
+ bpart->bdev->bio->Media->BlockSize, DEV_BSIZE);
+ return EIO;
+ }
+ dblk += le64toh(bpart->gpt.ent.ent_lba_start);
+ break;
default:
return EINVAL;
}
Index: src/sys/stand/efiboot/efiblock.h
diff -u src/sys/stand/efiboot/efiblock.h:1.2 src/sys/stand/efiboot/efiblock.h:1.3
--- src/sys/stand/efiboot/efiblock.h:1.2 Mon Aug 27 09:51:32 2018
+++ src/sys/stand/efiboot/efiblock.h Thu Nov 1 00:43:38 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: efiblock.h,v 1.2 2018/08/27 09:51:32 jmcneill Exp $ */
+/* $NetBSD: efiblock.h,v 1.3 2018/11/01 00:43:38 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -29,6 +29,7 @@
#include <sys/queue.h>
#include <sys/bootblock.h>
#include <sys/disklabel.h>
+#include <sys/disklabel_gpt.h>
enum efi_block_part_type {
EFI_BLOCK_PART_DISKLABEL,
@@ -52,12 +53,18 @@ struct efi_block_part_disklabel {
struct partition part;
};
+struct efi_block_part_gpt {
+ uint8_t fstype;
+ struct gpt_ent ent;
+};
+
struct efi_block_part {
uint32_t index;
struct efi_block_dev *bdev;
enum efi_block_part_type type;
union {
struct efi_block_part_disklabel disklabel;
+ struct efi_block_part_gpt gpt;
};
uint8_t hash[16];
Index: src/sys/stand/efiboot/efiboot.c
diff -u src/sys/stand/efiboot/efiboot.c:1.11 src/sys/stand/efiboot/efiboot.c:1.12
--- src/sys/stand/efiboot/efiboot.c:1.11 Wed Oct 31 13:00:35 2018
+++ src/sys/stand/efiboot/efiboot.c Thu Nov 1 00:43:38 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.c,v 1.11 2018/10/31 13:00:35 jmcneill Exp $ */
+/* $NetBSD: efiboot.c,v 1.12 2018/11/01 00:43:38 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -84,10 +84,10 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYS
efi_acpi_probe();
efi_fdt_probe();
- efi_file_system_probe();
- efi_block_probe();
efi_pxe_probe();
efi_net_probe();
+ efi_file_system_probe();
+ efi_block_probe();
boot();
Index: src/sys/stand/efiboot/efifdt.c
diff -u src/sys/stand/efiboot/efifdt.c:1.11 src/sys/stand/efiboot/efifdt.c:1.12
--- src/sys/stand/efiboot/efifdt.c:1.11 Wed Oct 31 12:59:43 2018
+++ src/sys/stand/efiboot/efifdt.c Thu Nov 1 00:43:38 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: efifdt.c,v 1.11 2018/10/31 12:59:43 jmcneill Exp $ */
+/* $NetBSD: efifdt.c,v 1.12 2018/11/01 00:43:38 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -219,6 +219,19 @@ efi_fdt_bootargs(const char *bootargs)
fdt_setprop_u32(fdt_data, chosen, "netbsd,partition",
bpart->index);
break;
+ case EFI_BLOCK_PART_GPT:
+ if (bpart->gpt.ent.ent_name[0] == 0x0000) {
+ fdt_setprop(fdt_data, chosen, "netbsd,gpt-guid",
+ bpart->hash, sizeof(bpart->hash));
+ } else {
+ char *label = NULL;
+ int rv = ucs2_to_utf8(bpart->gpt.ent.ent_name, &label);
+ if (rv == 0) {
+ fdt_setprop_string(fdt_data, chosen, "netbsd,gpt-label", label);
+ FreePool(label);
+ }
+ }
+ break;
default:
break;
}
Index: src/sys/stand/efiboot/version
diff -u src/sys/stand/efiboot/version:1.6 src/sys/stand/efiboot/version:1.7
--- src/sys/stand/efiboot/version:1.6 Sun Oct 28 10:17:47 2018
+++ src/sys/stand/efiboot/version Thu Nov 1 00:43:38 2018
@@ -1,4 +1,4 @@
-$NetBSD: version,v 1.6 2018/10/28 10:17:47 jmcneill Exp $
+$NetBSD: version,v 1.7 2018/11/01 00:43:38 jmcneill Exp $
NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this
file is important - make sure the entries are appended on end, last item
@@ -10,3 +10,4 @@ is taken as the current.
1.3: Add ACPI support.
1.4: Add bootfile support.
1.5: EFI runtime support.
+1.6: Add GPT support.