FreeBSD Bugzilla – Attachment 159109 Details for
Bug 201788
UEFI boot1.efi doesn't honor GPT bootme/bootonce flags
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Include gpt functionality
uefi.gpt.diff (text/plain), 9.88 KB, created by
holger
on 2015-07-23 13:28:05 UTC
(
hide
)
Description:
Include gpt functionality
Filename:
MIME Type:
Creator:
holger
Created:
2015-07-23 13:28:05 UTC
Size:
9.88 KB
patch
obsolete
>Index: common/gpt.c >=================================================================== >--- common/gpt.c (revision 285747) >+++ common/gpt.c (working copy) >@@ -34,9 +34,12 @@ > #error gpt.c works only for little endian architectures > #endif > >+#ifndef GPT_NO_INCLUDES > #include "crc32.h" >+#include "util.h" >+#endif >+ > #include "drv.h" >-#include "util.h" > #include "gpt.h" > > #define MAXTBLENTS 128 >@@ -43,7 +46,11 @@ > > static struct gpt_hdr hdr_primary, hdr_backup, *gpthdr; > static uint64_t hdr_primary_lba, hdr_backup_lba; >+#ifndef GPT_DYNAMIC_ALLOC > static struct gpt_ent table_primary[MAXTBLENTS], table_backup[MAXTBLENTS]; >+#else >+static struct gpt_ent *table_primary, *table_backup; >+#endif > static struct gpt_ent *gpttable; > static int curent, bootonce; > >@@ -53,6 +60,16 @@ > */ > static char *secbuf; > >+ >+#ifdef GPT_DYNAMIC_ALLOC >+void >+gptinit(void) >+{ >+ table_primary = gpt_mem_alloc(sizeof(*table_primary) * MAXTBLENTS); >+ table_backup = gpt_mem_alloc(sizeof(*table_backup) * MAXTBLENTS); >+} >+#endif >+ > static void > gptupdate(const char *which, struct dsk *dskp, struct gpt_hdr *hdr, > struct gpt_ent *table) >Index: common/gpt.h >=================================================================== >--- common/gpt.h (revision 285747) >+++ common/gpt.h (working copy) >@@ -36,4 +36,8 @@ > int gptfind(const uuid_t *uuid, struct dsk *dskp, int part); > void gptbootfailed(struct dsk *dskp); > >+#ifdef GPT_DYNAMIC_ALLOC >+void gptinit(void); >+#endif >+ > #endif /* !_GPT_H_ */ >Index: efi/boot1/Makefile >=================================================================== >--- efi/boot1/Makefile (revision 285747) >+++ efi/boot1/Makefile (working copy) >@@ -26,6 +26,8 @@ > .PATH: ${.CURDIR}/../loader > .PATH: ${.CURDIR}/../../common > CFLAGS+= -I${.CURDIR}/../../common >+CFLAGS+= -DBOOTPROG=\"boot1.uefi\" >+CFLAGS+= -DGPT_NO_INCLUDES=1 -DGPT_DYNAMIC_ALLOC=1 > > FILES= boot1.efi boot1.efifat > FILESMODE_boot1.efi= ${BINMODE} >@@ -73,7 +75,7 @@ > -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \ > --output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET} > >-boot1.o: ${.CURDIR}/../../common/ufsread.c >+boot1.o: ${.CURDIR}/../../common/ufsread.c ${.CURDIR}/../../common/gpt.c > > # The following inserts out objects into a template FAT file system > # created by generate-fat.sh >Index: efi/boot1/boot1.c >=================================================================== >--- efi/boot1/boot1.c (revision 285747) >+++ efi/boot1/boot1.c (working copy) >@@ -5,6 +5,8 @@ > * All rights reserved. > * Copyright (c) 2014 Nathan Whitehorn > * All rights reserved. >+ * Copyright (c) 2015 Holger Hans Peter Freyther >+ * All rights reserved. > * > * Redistribution and use in source and binary forms are freely > * permitted provided that the above copyright notice and this >@@ -22,12 +24,16 @@ > > #include <sys/param.h> > #include <sys/dirent.h> >+#include <sys/gpt.h> > #include <machine/elf.h> > #include <machine/stdarg.h> > > #include <efi.h> > #include <eficonsctl.h> >+#include <efipart.h> > >+#include "gpt.h" >+ > #define _PATH_LOADER "/boot/loader.efi" > #define _PATH_KERNEL "/boot/kernel/kernel" > >@@ -79,6 +85,15 @@ > } > > static void >+memset(void *b, int c, size_t len) >+{ >+ char *bp = b; >+ >+ while (len--) >+ *bp++ = (unsigned char)c; >+} >+ >+static void > bzero(void *b, size_t len) > { > char *p = b; >@@ -88,6 +103,20 @@ > } > > static int >+memcmp(const void *b1, const void *b2, size_t len) >+{ >+ const unsigned char *p1, *p2; >+ >+ for (p1 = b1, p2 = b2; len > 0; len--, p1++, p2++) { >+ if (*p1 != *p2) >+ return ((*p1) - (*p2)); >+ } >+ return (0); >+} >+#define bcmp(b1, b2, len) (memcmp((b1), (b2), (len)) != 0) >+ >+ >+static int > strcmp(const char *s1, const char *s2) > { > for (; *s1 == *s2 && *s1; s1++, s2++) >@@ -104,6 +133,10 @@ > static EFI_DEVICE_PATH *bootdevpath; > static EFI_HANDLE *bootdevhandle; > >+static const uuid_t freebsd_ufs_uuid = GPT_ENT_TYPE_FREEBSD_UFS; >+ >+static void attempt_gtpboot(EFI_BOOT_SERVICES *BS, EFI_HANDLE *handles, UINTN nparts); >+ > EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) > { > EFI_HANDLE handles[128]; >@@ -154,6 +187,8 @@ > &BlockIoProtocolGUID, NULL, &nparts, handles); > nparts /= sizeof(handles[0]); > >+ attempt_gtpboot(BS, handles, nparts); >+ > for (i = 0; i < nparts; i++) { > status = systab->BootServices->HandleProtocol(handles[i], > &DevicePathGUID, (void **)&devpath); >@@ -571,3 +606,199 @@ > while ((ul /= base) != 0); > return (p); > } >+ >+static uint32_t crc32(void *buf, size_t size) >+{ >+ EFI_STATUS status; >+ UINT32 crc; >+ >+ status = systab->BootServices->CalculateCrc32(buf, size, &crc); >+ if (EFI_ERROR(status)) >+ return 0; >+ return crc; >+} >+ >+/* >+ * We need to handle GPT ourselves. This means we find a >+ * disk and check for the GPT partition and then we need >+ * to find the handle to this device + partition. I didn't >+ * want to rely on the order devices are listed. >+ */ >+static void attempt_gtpboot(EFI_BOOT_SERVICES *BS, EFI_HANDLE *handles, UINTN nparts) >+{ >+ EFI_DEVICE_PATH *devpath; >+ EFI_BLOCK_IO *blkio; >+ EFI_STATUS status; >+ UINTN i, j; >+ char *path = _PATH_LOADER; >+ >+ gptinit(); >+ >+ for (i = 0; i < nparts; i++) { >+ MASTER_BOOT_RECORD *mbr; >+ struct dsk dsk; >+ >+ status = BS->HandleProtocol(handles[i], >+ &DevicePathGUID, (void **)&devpath); >+ if (EFI_ERROR(status)) >+ continue; >+ >+ while (!IsDevicePathEnd(NextDevicePathNode(devpath))) >+ devpath = NextDevicePathNode(devpath); >+ >+ /* We want devices like ATAPI.. etc and no disks */ >+ if (DevicePathType(devpath) != MESSAGING_DEVICE_PATH) >+ continue; >+ >+ status = BS->HandleProtocol(handles[i], >+ &BlockIoProtocolGUID, (void **)&blkio); >+ >+ if (EFI_ERROR(status)) >+ continue; >+ >+ /* check if this is a GTP device */ >+ status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, 0, >+ blkio->Media->BlockSize, __dmadat.secbuf); >+ if (EFI_ERROR(status)) >+ continue; >+ mbr = (MASTER_BOOT_RECORD *) __dmadat.secbuf; >+ for (j = 0; j < MAX_MBR_PARTITIONS; ++j) { >+ if (mbr->Partition[j].BootIndicator != 0x00) >+ continue; >+ if (mbr->Partition[j].OSIndicator != 0xEE) >+ continue; >+ if (EXTRACT_UINT32(mbr->Partition[j].StartingLBA) != 1) >+ continue; >+ break; >+ } >+ if (j == MAX_MBR_PARTITIONS) >+ continue; >+ >+ /* Load GPT table and identify partition to boot */ >+ dsk.bio = blkio; >+ dsk.part = -1; >+ dsk.start = 0; >+ if (gptread(&freebsd_ufs_uuid, &dsk, __dmadat.secbuf) == -1) { >+ printf("%s: unable to load GPT\n", BOOTPROG); >+ continue; >+ } >+ if (gptfind(&freebsd_ufs_uuid, &dsk, dsk.part) == -1) { >+ printf("%s: no UFS partition was found\n", BOOTPROG); >+ continue; >+ } >+ >+ /* >+ * Now find the matching partition or mark it as failure. >+ * The standard UEFI protocol can't list us the partition >+ * that was created for this device so we need to find a >+ * partition with the right partition number and then we >+ * can compare the device node before with the devicepath. >+ * This way we do not depend on the order the partitions >+ * and devices are listed. >+ */ >+ for (j = 0; j < nparts; ++j) { >+ EFI_DEVICE_PATH *logpart, *prev; >+ EFI_BLOCK_IO *partio; >+ HARDDRIVE_DEVICE_PATH *hdpath; >+ >+ status = BS->HandleProtocol(handles[j], >+ &DevicePathGUID, (void **)&logpart); >+ if (EFI_ERROR(status)) >+ continue; >+ >+ prev = logpart; >+ while (!IsDevicePathEnd(NextDevicePathNode(logpart))) { >+ prev = logpart; >+ logpart = NextDevicePathNode(logpart); >+ } >+ >+ >+ if (DevicePathType(logpart) != MEDIA_DEVICE_PATH) >+ continue; >+ if (DevicePathSubType(logpart) != HARDWARE_DEVICE_PATH) >+ continue; >+ >+ hdpath = (HARDDRIVE_DEVICE_PATH *) logpart; >+ if (hdpath->PartitionNumber != dsk.part) >+ continue; >+ >+ status = BS->HandleProtocol(handles[j], >+ &BlockIoProtocolGUID, (void **)&partio); >+ if (EFI_ERROR(status)) >+ continue; >+ >+ if (!partio->Media->LogicalPartition) >+ continue; >+ >+ /* check if the underlying device is the same? */ >+ if (DevicePathType(prev) != DevicePathType(devpath)) >+ continue; >+ if (DevicePathNodeLength(prev) != DevicePathNodeLength(devpath)) >+ continue; >+ if (memcmp(prev, devpath, DevicePathNodeLength(devpath)) != 0) >+ continue; >+ >+ if (domount(logpart, partio, 1) >= 0) { >+ bootdevhandle = handles[j]; >+ load(path); >+ } >+ } >+ >+ /* boot failed for this GPT partition */ >+ gptbootfailed(&dsk); >+ } >+ >+ printf("Failed with gptboot\n"); >+} >+ >+int drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) >+{ >+ EFI_STATUS status; >+ int size; >+ >+ lba = lba / (dskp->bio->Media->BlockSize / DEV_BSIZE); >+ size = nblk * DEV_BSIZE; >+ status = dskp->bio->ReadBlocks(dskp->bio, dskp->bio->Media->MediaId, lba, >+ size, buf); >+ >+ if (EFI_ERROR(status)) >+ return (-1); >+ >+ return (0); >+} >+ >+int drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) >+{ >+ EFI_STATUS status; >+ int size; >+ >+ lba = lba / (dskp->bio->Media->BlockSize / DEV_BSIZE); >+ size = nblk * DEV_BSIZE; >+ status = dskp->bio->WriteBlocks(dskp->bio, dskp->bio->Media->MediaId, lba, >+ size, buf); >+ if (EFI_ERROR(status)) >+ return (-1); >+ status = dskp->bio->FlushBlocks(dskp->bio); >+ if (EFI_ERROR(status)) >+ return (-1); >+ return 0; >+} >+ >+uint64_t drvsize(struct dsk *dskp) >+{ >+ return dskp->bio->Media->LastBlock; >+} >+ >+void *gpt_mem_alloc(size_t size) >+{ >+ void *mem; >+ EFI_STATUS status; >+ >+ status = systab->BootServices->AllocatePool(EfiLoaderData, >+ size, &mem); >+ if (EFI_ERROR(status)) >+ return NULL; >+ return mem; >+} >+ >+#include "gpt.c" >Index: efi/include/drv.h >=================================================================== >--- efi/include/drv.h (revision 0) >+++ efi/include/drv.h (working copy) >@@ -0,0 +1,10 @@ >+#ifndef _DRV_H_ >+#define _DRV_H_ >+ >+struct dsk { >+ EFI_BLOCK_IO *bio; >+ unsigned int part; >+ daddr_t start; >+}; >+ >+#endif > >Property changes on: efi/include/drv.h >___________________________________________________________________ >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Added: svn:keywords >## -0,0 +1 ## >+FreeBSD=%H >\ No newline at end of property
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 201788
: 159109