Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/stand/efiboot Add GPT support.
details: https://anonhg.NetBSD.org/src/rev/ad91a640cd11
branches: trunk
changeset: 445527:ad91a640cd11
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Thu Nov 01 00:43:38 2018 +0000
description:
Add GPT support.
diffstat:
sys/stand/efiboot/efiblock.c | 167 +++++++++++++++++++++++++++++++++++++++++-
sys/stand/efiboot/efiblock.h | 9 ++-
sys/stand/efiboot/efiboot.c | 6 +-
sys/stand/efiboot/efifdt.c | 15 +++-
sys/stand/efiboot/version | 3 +-
5 files changed, 188 insertions(+), 12 deletions(-)
diffs (truncated from 322 to 300 lines):
diff -r 7039e18ba8d5 -r ad91a640cd11 sys/stand/efiboot/efiblock.c
--- a/sys/stand/efiboot/efiblock.c Wed Oct 31 23:49:34 2018 +0000
+++ b/sys/stand/efiboot/efiblock.c Thu Nov 01 00:43:38 2018 +0000
@@ -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 <nonaka%netbsd.org@localhost>
@@ -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 @@
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 @@
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 @@
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 @@
}
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;
}
diff -r 7039e18ba8d5 -r ad91a640cd11 sys/stand/efiboot/efiblock.h
--- a/sys/stand/efiboot/efiblock.h Wed Oct 31 23:49:34 2018 +0000
+++ b/sys/stand/efiboot/efiblock.h Thu Nov 01 00:43:38 2018 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 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];
diff -r 7039e18ba8d5 -r ad91a640cd11 sys/stand/efiboot/efiboot.c
--- a/sys/stand/efiboot/efiboot.c Wed Oct 31 23:49:34 2018 +0000
+++ b/sys/stand/efiboot/efiboot.c Thu Nov 01 00:43:38 2018 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -84,10 +84,10 @@
efi_acpi_probe();
efi_fdt_probe();
+ efi_pxe_probe();
+ efi_net_probe();
efi_file_system_probe();
efi_block_probe();
- efi_pxe_probe();
- efi_net_probe();
boot();
diff -r 7039e18ba8d5 -r ad91a640cd11 sys/stand/efiboot/efifdt.c
--- a/sys/stand/efiboot/efifdt.c Wed Oct 31 23:49:34 2018 +0000
+++ b/sys/stand/efiboot/efifdt.c Thu Nov 01 00:43:38 2018 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -219,6 +219,19 @@
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) {
Home |
Main Index |
Thread Index |
Old Index