View | Details | Raw Unified | Return to bug 201788
Collapse All | Expand All

(-)common/gpt.c (-1 / +18 lines)
Lines 34-42 Link Here
34
#error gpt.c works only for little endian architectures
34
#error gpt.c works only for little endian architectures
35
#endif
35
#endif
36
36
37
#ifndef GPT_NO_INCLUDES
37
#include "crc32.h"
38
#include "crc32.h"
39
#include "util.h"
40
#endif
41
38
#include "drv.h"
42
#include "drv.h"
39
#include "util.h"
40
#include "gpt.h"
43
#include "gpt.h"
41
44
42
#define	MAXTBLENTS	128
45
#define	MAXTBLENTS	128
Lines 43-49 Link Here
43
46
44
static struct gpt_hdr hdr_primary, hdr_backup, *gpthdr;
47
static struct gpt_hdr hdr_primary, hdr_backup, *gpthdr;
45
static uint64_t hdr_primary_lba, hdr_backup_lba;
48
static uint64_t hdr_primary_lba, hdr_backup_lba;
49
#ifndef GPT_DYNAMIC_ALLOC
46
static struct gpt_ent table_primary[MAXTBLENTS], table_backup[MAXTBLENTS];
50
static struct gpt_ent table_primary[MAXTBLENTS], table_backup[MAXTBLENTS];
51
#else
52
static struct gpt_ent *table_primary, *table_backup;
53
#endif
47
static struct gpt_ent *gpttable;
54
static struct gpt_ent *gpttable;
48
static int curent, bootonce;
55
static int curent, bootonce;
49
56
Lines 53-58 Link Here
53
 */
60
 */
54
static char *secbuf;
61
static char *secbuf;
55
62
63
64
#ifdef GPT_DYNAMIC_ALLOC
65
void
66
gptinit(void)
67
{
68
	table_primary = gpt_mem_alloc(sizeof(*table_primary) * MAXTBLENTS);
69
	table_backup = gpt_mem_alloc(sizeof(*table_backup) * MAXTBLENTS);
70
}
71
#endif
72
56
static void
73
static void
57
gptupdate(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
74
gptupdate(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
58
    struct gpt_ent *table)
75
    struct gpt_ent *table)
(-)common/gpt.h (+4 lines)
Lines 36-39 Link Here
36
int gptfind(const uuid_t *uuid, struct dsk *dskp, int part);
36
int gptfind(const uuid_t *uuid, struct dsk *dskp, int part);
37
void gptbootfailed(struct dsk *dskp);
37
void gptbootfailed(struct dsk *dskp);
38
38
39
#ifdef GPT_DYNAMIC_ALLOC
40
void gptinit(void);
41
#endif
42
39
#endif	/* !_GPT_H_ */
43
#endif	/* !_GPT_H_ */
(-)efi/boot1/Makefile (-1 / +3 lines)
Lines 26-31 Link Here
26
.PATH:		${.CURDIR}/../loader
26
.PATH:		${.CURDIR}/../loader
27
.PATH:		${.CURDIR}/../../common
27
.PATH:		${.CURDIR}/../../common
28
CFLAGS+=	-I${.CURDIR}/../../common
28
CFLAGS+=	-I${.CURDIR}/../../common
29
CFLAGS+=	-DBOOTPROG=\"boot1.uefi\"
30
CFLAGS+=	-DGPT_NO_INCLUDES=1 -DGPT_DYNAMIC_ALLOC=1
29
31
30
FILES=	boot1.efi boot1.efifat
32
FILES=	boot1.efi boot1.efifat
31
FILESMODE_boot1.efi=	${BINMODE}
33
FILESMODE_boot1.efi=	${BINMODE}
Lines 73-79 Link Here
73
		-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
75
		-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
74
		--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
76
		--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
75
77
76
boot1.o: ${.CURDIR}/../../common/ufsread.c
78
boot1.o: ${.CURDIR}/../../common/ufsread.c ${.CURDIR}/../../common/gpt.c
77
79
78
# The following inserts out objects into a template FAT file system
80
# The following inserts out objects into a template FAT file system
79
# created by generate-fat.sh
81
# created by generate-fat.sh
(-)efi/boot1/boot1.c (+231 lines)
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"
(-)efi/include/drv.h (+10 lines)
Line 0 Link Here
1
#ifndef _DRV_H_
2
#define _DRV_H_
3
4
struct dsk {
5
	EFI_BLOCK_IO *bio;
6
	unsigned int part;
7
	daddr_t start;
8
};
9
10
#endif

Return to bug 201788