Lines 5-10
Link Here
|
5 |
* All rights reserved. |
5 |
* All rights reserved. |
6 |
* Copyright (c) 2014 Nathan Whitehorn |
6 |
* Copyright (c) 2014 Nathan Whitehorn |
7 |
* All rights reserved. |
7 |
* All rights reserved. |
|
|
8 |
* Copyright (c) 2015 Holger Hans Peter Freyther |
9 |
* All rights reserved. |
8 |
* |
10 |
* |
9 |
* Redistribution and use in source and binary forms are freely |
11 |
* Redistribution and use in source and binary forms are freely |
10 |
* permitted provided that the above copyright notice and this |
12 |
* permitted provided that the above copyright notice and this |
Lines 22-33
Link Here
|
22 |
|
24 |
|
23 |
#include <sys/param.h> |
25 |
#include <sys/param.h> |
24 |
#include <sys/dirent.h> |
26 |
#include <sys/dirent.h> |
|
|
27 |
#include <sys/gpt.h> |
25 |
#include <machine/elf.h> |
28 |
#include <machine/elf.h> |
26 |
#include <machine/stdarg.h> |
29 |
#include <machine/stdarg.h> |
27 |
|
30 |
|
28 |
#include <efi.h> |
31 |
#include <efi.h> |
29 |
#include <eficonsctl.h> |
32 |
#include <eficonsctl.h> |
|
|
33 |
#include <efipart.h> |
30 |
|
34 |
|
|
|
35 |
#include "gpt.h" |
36 |
|
31 |
#define _PATH_LOADER "/boot/loader.efi" |
37 |
#define _PATH_LOADER "/boot/loader.efi" |
32 |
#define _PATH_KERNEL "/boot/kernel/kernel" |
38 |
#define _PATH_KERNEL "/boot/kernel/kernel" |
33 |
|
39 |
|
Lines 79-84
Link Here
|
79 |
} |
85 |
} |
80 |
|
86 |
|
81 |
static void |
87 |
static void |
|
|
88 |
memset(void *b, int c, size_t len) |
89 |
{ |
90 |
char *bp = b; |
91 |
|
92 |
while (len--) |
93 |
*bp++ = (unsigned char)c; |
94 |
} |
95 |
|
96 |
static void |
82 |
bzero(void *b, size_t len) |
97 |
bzero(void *b, size_t len) |
83 |
{ |
98 |
{ |
84 |
char *p = b; |
99 |
char *p = b; |
Lines 88-93
Link Here
|
88 |
} |
103 |
} |
89 |
|
104 |
|
90 |
static int |
105 |
static int |
|
|
106 |
memcmp(const void *b1, const void *b2, size_t len) |
107 |
{ |
108 |
const unsigned char *p1, *p2; |
109 |
|
110 |
for (p1 = b1, p2 = b2; len > 0; len--, p1++, p2++) { |
111 |
if (*p1 != *p2) |
112 |
return ((*p1) - (*p2)); |
113 |
} |
114 |
return (0); |
115 |
} |
116 |
#define bcmp(b1, b2, len) (memcmp((b1), (b2), (len)) != 0) |
117 |
|
118 |
|
119 |
static int |
91 |
strcmp(const char *s1, const char *s2) |
120 |
strcmp(const char *s1, const char *s2) |
92 |
{ |
121 |
{ |
93 |
for (; *s1 == *s2 && *s1; s1++, s2++) |
122 |
for (; *s1 == *s2 && *s1; s1++, s2++) |
Lines 104-109
Link Here
|
104 |
static EFI_DEVICE_PATH *bootdevpath; |
133 |
static EFI_DEVICE_PATH *bootdevpath; |
105 |
static EFI_HANDLE *bootdevhandle; |
134 |
static EFI_HANDLE *bootdevhandle; |
106 |
|
135 |
|
|
|
136 |
static const uuid_t freebsd_ufs_uuid = GPT_ENT_TYPE_FREEBSD_UFS; |
137 |
|
138 |
static void attempt_gtpboot(EFI_BOOT_SERVICES *BS, EFI_HANDLE *handles, UINTN nparts); |
139 |
|
107 |
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) |
140 |
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) |
108 |
{ |
141 |
{ |
109 |
EFI_HANDLE handles[128]; |
142 |
EFI_HANDLE handles[128]; |
Lines 154-159
Link Here
|
154 |
&BlockIoProtocolGUID, NULL, &nparts, handles); |
187 |
&BlockIoProtocolGUID, NULL, &nparts, handles); |
155 |
nparts /= sizeof(handles[0]); |
188 |
nparts /= sizeof(handles[0]); |
156 |
|
189 |
|
|
|
190 |
attempt_gtpboot(BS, handles, nparts); |
191 |
|
157 |
for (i = 0; i < nparts; i++) { |
192 |
for (i = 0; i < nparts; i++) { |
158 |
status = systab->BootServices->HandleProtocol(handles[i], |
193 |
status = systab->BootServices->HandleProtocol(handles[i], |
159 |
&DevicePathGUID, (void **)&devpath); |
194 |
&DevicePathGUID, (void **)&devpath); |
Lines 571-573
Link Here
|
571 |
while ((ul /= base) != 0); |
606 |
while ((ul /= base) != 0); |
572 |
return (p); |
607 |
return (p); |
573 |
} |
608 |
} |
|
|
609 |
|
610 |
static uint32_t crc32(void *buf, size_t size) |
611 |
{ |
612 |
EFI_STATUS status; |
613 |
UINT32 crc; |
614 |
|
615 |
status = systab->BootServices->CalculateCrc32(buf, size, &crc); |
616 |
if (EFI_ERROR(status)) |
617 |
return 0; |
618 |
return crc; |
619 |
} |
620 |
|
621 |
/* |
622 |
* We need to handle GPT ourselves. This means we find a |
623 |
* disk and check for the GPT partition and then we need |
624 |
* to find the handle to this device + partition. I didn't |
625 |
* want to rely on the order devices are listed. |
626 |
*/ |
627 |
static void attempt_gtpboot(EFI_BOOT_SERVICES *BS, EFI_HANDLE *handles, UINTN nparts) |
628 |
{ |
629 |
EFI_DEVICE_PATH *devpath; |
630 |
EFI_BLOCK_IO *blkio; |
631 |
EFI_STATUS status; |
632 |
UINTN i, j; |
633 |
char *path = _PATH_LOADER; |
634 |
|
635 |
gptinit(); |
636 |
|
637 |
for (i = 0; i < nparts; i++) { |
638 |
MASTER_BOOT_RECORD *mbr; |
639 |
struct dsk dsk; |
640 |
|
641 |
status = BS->HandleProtocol(handles[i], |
642 |
&DevicePathGUID, (void **)&devpath); |
643 |
if (EFI_ERROR(status)) |
644 |
continue; |
645 |
|
646 |
while (!IsDevicePathEnd(NextDevicePathNode(devpath))) |
647 |
devpath = NextDevicePathNode(devpath); |
648 |
|
649 |
/* We want devices like ATAPI.. etc and no disks */ |
650 |
if (DevicePathType(devpath) != MESSAGING_DEVICE_PATH) |
651 |
continue; |
652 |
|
653 |
status = BS->HandleProtocol(handles[i], |
654 |
&BlockIoProtocolGUID, (void **)&blkio); |
655 |
|
656 |
if (EFI_ERROR(status)) |
657 |
continue; |
658 |
|
659 |
/* check if this is a GTP device */ |
660 |
status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, 0, |
661 |
blkio->Media->BlockSize, __dmadat.secbuf); |
662 |
if (EFI_ERROR(status)) |
663 |
continue; |
664 |
mbr = (MASTER_BOOT_RECORD *) __dmadat.secbuf; |
665 |
for (j = 0; j < MAX_MBR_PARTITIONS; ++j) { |
666 |
if (mbr->Partition[j].BootIndicator != 0x00) |
667 |
continue; |
668 |
if (mbr->Partition[j].OSIndicator != 0xEE) |
669 |
continue; |
670 |
if (EXTRACT_UINT32(mbr->Partition[j].StartingLBA) != 1) |
671 |
continue; |
672 |
break; |
673 |
} |
674 |
if (j == MAX_MBR_PARTITIONS) |
675 |
continue; |
676 |
|
677 |
/* Load GPT table and identify partition to boot */ |
678 |
dsk.bio = blkio; |
679 |
dsk.part = -1; |
680 |
dsk.start = 0; |
681 |
if (gptread(&freebsd_ufs_uuid, &dsk, __dmadat.secbuf) == -1) { |
682 |
printf("%s: unable to load GPT\n", BOOTPROG); |
683 |
continue; |
684 |
} |
685 |
if (gptfind(&freebsd_ufs_uuid, &dsk, dsk.part) == -1) { |
686 |
printf("%s: no UFS partition was found\n", BOOTPROG); |
687 |
continue; |
688 |
} |
689 |
|
690 |
/* |
691 |
* Now find the matching partition or mark it as failure. |
692 |
* The standard UEFI protocol can't list us the partition |
693 |
* that was created for this device so we need to find a |
694 |
* partition with the right partition number and then we |
695 |
* can compare the device node before with the devicepath. |
696 |
* This way we do not depend on the order the partitions |
697 |
* and devices are listed. |
698 |
*/ |
699 |
for (j = 0; j < nparts; ++j) { |
700 |
EFI_DEVICE_PATH *logpart, *prev; |
701 |
EFI_BLOCK_IO *partio; |
702 |
HARDDRIVE_DEVICE_PATH *hdpath; |
703 |
|
704 |
status = BS->HandleProtocol(handles[j], |
705 |
&DevicePathGUID, (void **)&logpart); |
706 |
if (EFI_ERROR(status)) |
707 |
continue; |
708 |
|
709 |
prev = logpart; |
710 |
while (!IsDevicePathEnd(NextDevicePathNode(logpart))) { |
711 |
prev = logpart; |
712 |
logpart = NextDevicePathNode(logpart); |
713 |
} |
714 |
|
715 |
|
716 |
if (DevicePathType(logpart) != MEDIA_DEVICE_PATH) |
717 |
continue; |
718 |
if (DevicePathSubType(logpart) != HARDWARE_DEVICE_PATH) |
719 |
continue; |
720 |
|
721 |
hdpath = (HARDDRIVE_DEVICE_PATH *) logpart; |
722 |
if (hdpath->PartitionNumber != dsk.part) |
723 |
continue; |
724 |
|
725 |
status = BS->HandleProtocol(handles[j], |
726 |
&BlockIoProtocolGUID, (void **)&partio); |
727 |
if (EFI_ERROR(status)) |
728 |
continue; |
729 |
|
730 |
if (!partio->Media->LogicalPartition) |
731 |
continue; |
732 |
|
733 |
/* check if the underlying device is the same? */ |
734 |
if (DevicePathType(prev) != DevicePathType(devpath)) |
735 |
continue; |
736 |
if (DevicePathNodeLength(prev) != DevicePathNodeLength(devpath)) |
737 |
continue; |
738 |
if (memcmp(prev, devpath, DevicePathNodeLength(devpath)) != 0) |
739 |
continue; |
740 |
|
741 |
if (domount(logpart, partio, 1) >= 0) { |
742 |
bootdevhandle = handles[j]; |
743 |
load(path); |
744 |
} |
745 |
} |
746 |
|
747 |
/* boot failed for this GPT partition */ |
748 |
gptbootfailed(&dsk); |
749 |
} |
750 |
|
751 |
printf("Failed with gptboot\n"); |
752 |
} |
753 |
|
754 |
int drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) |
755 |
{ |
756 |
EFI_STATUS status; |
757 |
int size; |
758 |
|
759 |
lba = lba / (dskp->bio->Media->BlockSize / DEV_BSIZE); |
760 |
size = nblk * DEV_BSIZE; |
761 |
status = dskp->bio->ReadBlocks(dskp->bio, dskp->bio->Media->MediaId, lba, |
762 |
size, buf); |
763 |
|
764 |
if (EFI_ERROR(status)) |
765 |
return (-1); |
766 |
|
767 |
return (0); |
768 |
} |
769 |
|
770 |
int drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) |
771 |
{ |
772 |
EFI_STATUS status; |
773 |
int size; |
774 |
|
775 |
lba = lba / (dskp->bio->Media->BlockSize / DEV_BSIZE); |
776 |
size = nblk * DEV_BSIZE; |
777 |
status = dskp->bio->WriteBlocks(dskp->bio, dskp->bio->Media->MediaId, lba, |
778 |
size, buf); |
779 |
if (EFI_ERROR(status)) |
780 |
return (-1); |
781 |
status = dskp->bio->FlushBlocks(dskp->bio); |
782 |
if (EFI_ERROR(status)) |
783 |
return (-1); |
784 |
return 0; |
785 |
} |
786 |
|
787 |
uint64_t drvsize(struct dsk *dskp) |
788 |
{ |
789 |
return dskp->bio->Media->LastBlock; |
790 |
} |
791 |
|
792 |
void *gpt_mem_alloc(size_t size) |
793 |
{ |
794 |
void *mem; |
795 |
EFI_STATUS status; |
796 |
|
797 |
status = systab->BootServices->AllocatePool(EfiLoaderData, |
798 |
size, &mem); |
799 |
if (EFI_ERROR(status)) |
800 |
return NULL; |
801 |
return mem; |
802 |
} |
803 |
|
804 |
#include "gpt.c" |