boot1.c revision 264391
1264391Snwhitehorn/*-
2264391Snwhitehorn * Copyright (c) 1998 Robert Nordier
3264391Snwhitehorn * All rights reserved.
4264391Snwhitehorn * Copyright (c) 2001 Robert Drehmel
5264391Snwhitehorn * All rights reserved.
6264391Snwhitehorn *
7264391Snwhitehorn * Redistribution and use in source and binary forms are freely
8264391Snwhitehorn * permitted provided that the above copyright notice and this
9264391Snwhitehorn * paragraph and the following disclaimer are duplicated in all
10264391Snwhitehorn * such forms.
11264391Snwhitehorn *
12264391Snwhitehorn * This software is provided "AS IS" and without any express or
13264391Snwhitehorn * implied warranties, including, without limitation, the implied
14264391Snwhitehorn * warranties of merchantability and fitness for a particular
15264391Snwhitehorn * purpose.
16264391Snwhitehorn */
17264391Snwhitehorn
18264391Snwhitehorn#include <sys/cdefs.h>
19264391Snwhitehorn__FBSDID("$FreeBSD: head/sys/boot/amd64/boot1.efi/boot1.c 264391 2014-04-13 01:14:25Z nwhitehorn $");
20264391Snwhitehorn
21264391Snwhitehorn#include <sys/param.h>
22264391Snwhitehorn#include <sys/dirent.h>
23264391Snwhitehorn#include <machine/elf.h>
24264391Snwhitehorn#include <machine/stdarg.h>
25264391Snwhitehorn
26264391Snwhitehorn#include <efi.h>
27264391Snwhitehorn
28264391Snwhitehorn#define _PATH_LOADER	"/boot/loader.efi"
29264391Snwhitehorn#define _PATH_KERNEL	"/boot/kernel/kernel"
30264391Snwhitehorn
31264391Snwhitehorn#define BSIZEMAX	16384
32264391Snwhitehorn
33264391Snwhitehorntypedef int putc_func_t(char c, void *arg);
34264391Snwhitehorn
35264391Snwhitehornstruct sp_data {
36264391Snwhitehorn	char	*sp_buf;
37264391Snwhitehorn	u_int	sp_len;
38264391Snwhitehorn	u_int	sp_size;
39264391Snwhitehorn};
40264391Snwhitehorn
41264391Snwhitehornstatic const char digits[] = "0123456789abcdef";
42264391Snwhitehorn
43264391Snwhitehornstatic void panic(const char *fmt, ...) __dead2;
44264391Snwhitehornstatic int printf(const char *fmt, ...);
45264391Snwhitehornstatic int putchar(char c, void *arg);
46264391Snwhitehornstatic int vprintf(const char *fmt, va_list ap);
47264391Snwhitehornstatic int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
48264391Snwhitehorn
49264391Snwhitehornstatic int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
50264391Snwhitehornstatic int __putc(char c, void *arg);
51264391Snwhitehornstatic int __puts(const char *s, putc_func_t *putc, void *arg);
52264391Snwhitehornstatic int __sputc(char c, void *arg);
53264391Snwhitehornstatic char *__uitoa(char *buf, u_int val, int base);
54264391Snwhitehornstatic char *__ultoa(char *buf, u_long val, int base);
55264391Snwhitehorn
56264391Snwhitehornstatic int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
57264391Snwhitehornstatic void load(const char *fname);
58264391Snwhitehorn
59264391SnwhitehornEFI_SYSTEM_TABLE *systab;
60264391SnwhitehornEFI_HANDLE *image;
61264391Snwhitehorn
62264391Snwhitehornstatic void
63264391Snwhitehornbcopy(const void *src, void *dst, size_t len)
64264391Snwhitehorn{
65264391Snwhitehorn	const char *s = src;
66264391Snwhitehorn	char *d = dst;
67264391Snwhitehorn
68264391Snwhitehorn	while (len-- != 0)
69264391Snwhitehorn		*d++ = *s++;
70264391Snwhitehorn}
71264391Snwhitehorn
72264391Snwhitehornstatic void
73264391Snwhitehornmemcpy(void *dst, const void *src, size_t len)
74264391Snwhitehorn{
75264391Snwhitehorn	bcopy(src, dst, len);
76264391Snwhitehorn}
77264391Snwhitehorn
78264391Snwhitehornstatic void
79264391Snwhitehornbzero(void *b, size_t len)
80264391Snwhitehorn{
81264391Snwhitehorn	char *p = b;
82264391Snwhitehorn
83264391Snwhitehorn	while (len-- != 0)
84264391Snwhitehorn		*p++ = 0;
85264391Snwhitehorn}
86264391Snwhitehorn
87264391Snwhitehornstatic int
88264391Snwhitehornstrcmp(const char *s1, const char *s2)
89264391Snwhitehorn{
90264391Snwhitehorn	for (; *s1 == *s2 && *s1; s1++, s2++)
91264391Snwhitehorn		;
92264391Snwhitehorn	return ((u_char)*s1 - (u_char)*s2);
93264391Snwhitehorn}
94264391Snwhitehorn
95264391Snwhitehornstatic EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
96264391Snwhitehornstatic EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
97264391Snwhitehornstatic EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
98264391Snwhitehorn
99264391Snwhitehornstatic EFI_BLOCK_IO *bootdev;
100264391Snwhitehornstatic EFI_DEVICE_PATH *bootdevpath;
101264391Snwhitehornstatic EFI_HANDLE *bootdevhandle;
102264391Snwhitehorn
103264391SnwhitehornEFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
104264391Snwhitehorn{
105264391Snwhitehorn	EFI_HANDLE handles[128];
106264391Snwhitehorn	EFI_BLOCK_IO *blkio;
107264391Snwhitehorn	UINTN i, nparts = sizeof(handles);
108264391Snwhitehorn	EFI_STATUS status;
109264391Snwhitehorn	EFI_DEVICE_PATH *devpath;
110264391Snwhitehorn	char *path = _PATH_LOADER;
111264391Snwhitehorn
112264391Snwhitehorn	systab = Xsystab;
113264391Snwhitehorn	image = Ximage;
114264391Snwhitehorn
115264391Snwhitehorn	printf(" \n>> FreeBSD EFI boot block\n");
116264391Snwhitehorn	printf("   Loader path: %s\n", path);
117264391Snwhitehorn
118264391Snwhitehorn	status = systab->BootServices->LocateHandle(ByProtocol,
119264391Snwhitehorn	    &BlockIoProtocolGUID, NULL, &nparts, handles);
120264391Snwhitehorn	nparts /= sizeof(handles[0]);
121264391Snwhitehorn
122264391Snwhitehorn	for (i = 0; i < nparts; i++) {
123264391Snwhitehorn		status = systab->BootServices->HandleProtocol(handles[i],
124264391Snwhitehorn		    &DevicePathGUID, (void **)&devpath);
125264391Snwhitehorn		if (EFI_ERROR(status))
126264391Snwhitehorn			continue;
127264391Snwhitehorn
128264391Snwhitehorn		while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
129264391Snwhitehorn			devpath = NextDevicePathNode(devpath);
130264391Snwhitehorn
131264391Snwhitehorn		status = systab->BootServices->HandleProtocol(handles[i],
132264391Snwhitehorn		    &BlockIoProtocolGUID, (void **)&blkio);
133264391Snwhitehorn		if (EFI_ERROR(status))
134264391Snwhitehorn			continue;
135264391Snwhitehorn
136264391Snwhitehorn		if (!blkio->Media->LogicalPartition)
137264391Snwhitehorn			continue;
138264391Snwhitehorn
139264391Snwhitehorn		if (domount(devpath, blkio, 1) >= 0)
140264391Snwhitehorn			break;
141264391Snwhitehorn	}
142264391Snwhitehorn
143264391Snwhitehorn	if (i == nparts)
144264391Snwhitehorn		panic("No bootable partition found");
145264391Snwhitehorn
146264391Snwhitehorn	bootdevhandle = handles[i];
147264391Snwhitehorn	load(path);
148264391Snwhitehorn
149264391Snwhitehorn	panic("Load failed");
150264391Snwhitehorn
151264391Snwhitehorn	return EFI_SUCCESS;
152264391Snwhitehorn}
153264391Snwhitehorn
154264391Snwhitehornstatic int
155264391Snwhitehorndskread(void *buf, u_int64_t lba, int nblk)
156264391Snwhitehorn{
157264391Snwhitehorn	EFI_STATUS status;
158264391Snwhitehorn
159264391Snwhitehorn	status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
160264391Snwhitehorn	    nblk * bootdev->Media->BlockSize, buf);
161264391Snwhitehorn
162264391Snwhitehorn	if (EFI_ERROR(status))
163264391Snwhitehorn		return (-1);
164264391Snwhitehorn
165264391Snwhitehorn	return (0);
166264391Snwhitehorn}
167264391Snwhitehorn
168264391Snwhitehorn#include "ufsread.c"
169264391Snwhitehorn
170264391Snwhitehornstatic struct dmadat __dmadat;
171264391Snwhitehorn
172264391Snwhitehornstatic int
173264391Snwhitehorndomount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
174264391Snwhitehorn{
175264391Snwhitehorn
176264391Snwhitehorn	dmadat = &__dmadat;
177264391Snwhitehorn	bootdev = blkio;
178264391Snwhitehorn	bootdevpath = device;
179264391Snwhitehorn	if (fsread(0, NULL, 0)) {
180264391Snwhitehorn		if (!quiet)
181264391Snwhitehorn			printf("domount: can't read superblock\n");
182264391Snwhitehorn		return (-1);
183264391Snwhitehorn	}
184264391Snwhitehorn	if (!quiet)
185264391Snwhitehorn		printf("Succesfully mounted UFS filesystem\n");
186264391Snwhitehorn	return (0);
187264391Snwhitehorn}
188264391Snwhitehorn
189264391Snwhitehornstatic void
190264391Snwhitehornload(const char *fname)
191264391Snwhitehorn{
192264391Snwhitehorn	ufs_ino_t ino;
193264391Snwhitehorn	EFI_STATUS status;
194264391Snwhitehorn	EFI_HANDLE loaderhandle;
195264391Snwhitehorn	EFI_LOADED_IMAGE *loaded_image;
196264391Snwhitehorn	void *buffer;
197264391Snwhitehorn	size_t bufsize;
198264391Snwhitehorn
199264391Snwhitehorn	if ((ino = lookup(fname)) == 0) {
200264391Snwhitehorn		printf("File %s not found\n", fname);
201264391Snwhitehorn		return;
202264391Snwhitehorn	}
203264391Snwhitehorn
204264391Snwhitehorn	bufsize = fsread(ino, NULL, -1);
205264391Snwhitehorn	status = systab->BootServices->AllocatePool(EfiLoaderData,
206264391Snwhitehorn	    bufsize, &buffer);
207264391Snwhitehorn	fsread(ino, buffer, bufsize);
208264391Snwhitehorn
209264391Snwhitehorn	/* XXX: For secure boot, we need our own loader here */
210264391Snwhitehorn	status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
211264391Snwhitehorn	    buffer, bufsize, &loaderhandle);
212264391Snwhitehorn
213264391Snwhitehorn	status = systab->BootServices->HandleProtocol(loaderhandle,
214264391Snwhitehorn	    &LoadedImageGUID, (VOID**)&loaded_image);
215264391Snwhitehorn	loaded_image->DeviceHandle = bootdevhandle;
216264391Snwhitehorn
217264391Snwhitehorn	status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
218264391Snwhitehorn}
219264391Snwhitehorn
220264391Snwhitehornstatic void
221264391Snwhitehornpanic(const char *fmt, ...)
222264391Snwhitehorn{
223264391Snwhitehorn	char buf[128];
224264391Snwhitehorn	va_list ap;
225264391Snwhitehorn
226264391Snwhitehorn	va_start(ap, fmt);
227264391Snwhitehorn	vsnprintf(buf, sizeof buf, fmt, ap);
228264391Snwhitehorn	printf("panic: %s\n", buf);
229264391Snwhitehorn	va_end(ap);
230264391Snwhitehorn
231264391Snwhitehorn	while (1) {}
232264391Snwhitehorn}
233264391Snwhitehorn
234264391Snwhitehornstatic int
235264391Snwhitehornprintf(const char *fmt, ...)
236264391Snwhitehorn{
237264391Snwhitehorn	va_list ap;
238264391Snwhitehorn	int ret;
239264391Snwhitehorn
240264391Snwhitehorn	/* Don't annoy the user as we probe for partitions */
241264391Snwhitehorn	if (strcmp(fmt,"Not ufs\n") == 0)
242264391Snwhitehorn		return 0;
243264391Snwhitehorn
244264391Snwhitehorn	va_start(ap, fmt);
245264391Snwhitehorn	ret = vprintf(fmt, ap);
246264391Snwhitehorn	va_end(ap);
247264391Snwhitehorn	return (ret);
248264391Snwhitehorn}
249264391Snwhitehorn
250264391Snwhitehornstatic int
251264391Snwhitehornputchar(char c, void *arg)
252264391Snwhitehorn{
253264391Snwhitehorn	CHAR16 buf[2];
254264391Snwhitehorn
255264391Snwhitehorn	if (c == '\n') {
256264391Snwhitehorn		buf[0] = '\r';
257264391Snwhitehorn		buf[1] = 0;
258264391Snwhitehorn		systab->ConOut->OutputString(systab->ConOut, buf);
259264391Snwhitehorn	}
260264391Snwhitehorn	buf[0] = c;
261264391Snwhitehorn	buf[1] = 0;
262264391Snwhitehorn	systab->ConOut->OutputString(systab->ConOut, buf);
263264391Snwhitehorn	return (1);
264264391Snwhitehorn}
265264391Snwhitehorn
266264391Snwhitehornstatic int
267264391Snwhitehornvprintf(const char *fmt, va_list ap)
268264391Snwhitehorn{
269264391Snwhitehorn	int ret;
270264391Snwhitehorn
271264391Snwhitehorn	ret = __printf(fmt, putchar, 0, ap);
272264391Snwhitehorn	return (ret);
273264391Snwhitehorn}
274264391Snwhitehorn
275264391Snwhitehornstatic int
276264391Snwhitehornvsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
277264391Snwhitehorn{
278264391Snwhitehorn	struct sp_data sp;
279264391Snwhitehorn	int ret;
280264391Snwhitehorn
281264391Snwhitehorn	sp.sp_buf = str;
282264391Snwhitehorn	sp.sp_len = 0;
283264391Snwhitehorn	sp.sp_size = sz;
284264391Snwhitehorn	ret = __printf(fmt, __sputc, &sp, ap);
285264391Snwhitehorn	return (ret);
286264391Snwhitehorn}
287264391Snwhitehorn
288264391Snwhitehornstatic int
289264391Snwhitehorn__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
290264391Snwhitehorn{
291264391Snwhitehorn	char buf[(sizeof(long) * 8) + 1];
292264391Snwhitehorn	char *nbuf;
293264391Snwhitehorn	u_long ul;
294264391Snwhitehorn	u_int ui;
295264391Snwhitehorn	int lflag;
296264391Snwhitehorn	int sflag;
297264391Snwhitehorn	char *s;
298264391Snwhitehorn	int pad;
299264391Snwhitehorn	int ret;
300264391Snwhitehorn	int c;
301264391Snwhitehorn
302264391Snwhitehorn	nbuf = &buf[sizeof buf - 1];
303264391Snwhitehorn	ret = 0;
304264391Snwhitehorn	while ((c = *fmt++) != 0) {
305264391Snwhitehorn		if (c != '%') {
306264391Snwhitehorn			ret += putc(c, arg);
307264391Snwhitehorn			continue;
308264391Snwhitehorn		}
309264391Snwhitehorn		lflag = 0;
310264391Snwhitehorn		sflag = 0;
311264391Snwhitehorn		pad = 0;
312264391Snwhitehornreswitch:	c = *fmt++;
313264391Snwhitehorn		switch (c) {
314264391Snwhitehorn		case '#':
315264391Snwhitehorn			sflag = 1;
316264391Snwhitehorn			goto reswitch;
317264391Snwhitehorn		case '%':
318264391Snwhitehorn			ret += putc('%', arg);
319264391Snwhitehorn			break;
320264391Snwhitehorn		case 'c':
321264391Snwhitehorn			c = va_arg(ap, int);
322264391Snwhitehorn			ret += putc(c, arg);
323264391Snwhitehorn			break;
324264391Snwhitehorn		case 'd':
325264391Snwhitehorn			if (lflag == 0) {
326264391Snwhitehorn				ui = (u_int)va_arg(ap, int);
327264391Snwhitehorn				if (ui < (int)ui) {
328264391Snwhitehorn					ui = -ui;
329264391Snwhitehorn					ret += putc('-', arg);
330264391Snwhitehorn				}
331264391Snwhitehorn				s = __uitoa(nbuf, ui, 10);
332264391Snwhitehorn			} else {
333264391Snwhitehorn				ul = (u_long)va_arg(ap, long);
334264391Snwhitehorn				if (ul < (long)ul) {
335264391Snwhitehorn					ul = -ul;
336264391Snwhitehorn					ret += putc('-', arg);
337264391Snwhitehorn				}
338264391Snwhitehorn				s = __ultoa(nbuf, ul, 10);
339264391Snwhitehorn			}
340264391Snwhitehorn			ret += __puts(s, putc, arg);
341264391Snwhitehorn			break;
342264391Snwhitehorn		case 'l':
343264391Snwhitehorn			lflag = 1;
344264391Snwhitehorn			goto reswitch;
345264391Snwhitehorn		case 'o':
346264391Snwhitehorn			if (lflag == 0) {
347264391Snwhitehorn				ui = (u_int)va_arg(ap, u_int);
348264391Snwhitehorn				s = __uitoa(nbuf, ui, 8);
349264391Snwhitehorn			} else {
350264391Snwhitehorn				ul = (u_long)va_arg(ap, u_long);
351264391Snwhitehorn				s = __ultoa(nbuf, ul, 8);
352264391Snwhitehorn			}
353264391Snwhitehorn			ret += __puts(s, putc, arg);
354264391Snwhitehorn			break;
355264391Snwhitehorn		case 'p':
356264391Snwhitehorn			ul = (u_long)va_arg(ap, void *);
357264391Snwhitehorn			s = __ultoa(nbuf, ul, 16);
358264391Snwhitehorn			ret += __puts("0x", putc, arg);
359264391Snwhitehorn			ret += __puts(s, putc, arg);
360264391Snwhitehorn			break;
361264391Snwhitehorn		case 's':
362264391Snwhitehorn			s = va_arg(ap, char *);
363264391Snwhitehorn			ret += __puts(s, putc, arg);
364264391Snwhitehorn			break;
365264391Snwhitehorn		case 'u':
366264391Snwhitehorn			if (lflag == 0) {
367264391Snwhitehorn				ui = va_arg(ap, u_int);
368264391Snwhitehorn				s = __uitoa(nbuf, ui, 10);
369264391Snwhitehorn			} else {
370264391Snwhitehorn				ul = va_arg(ap, u_long);
371264391Snwhitehorn				s = __ultoa(nbuf, ul, 10);
372264391Snwhitehorn			}
373264391Snwhitehorn			ret += __puts(s, putc, arg);
374264391Snwhitehorn			break;
375264391Snwhitehorn		case 'x':
376264391Snwhitehorn			if (lflag == 0) {
377264391Snwhitehorn				ui = va_arg(ap, u_int);
378264391Snwhitehorn				s = __uitoa(nbuf, ui, 16);
379264391Snwhitehorn			} else {
380264391Snwhitehorn				ul = va_arg(ap, u_long);
381264391Snwhitehorn				s = __ultoa(nbuf, ul, 16);
382264391Snwhitehorn			}
383264391Snwhitehorn			if (sflag)
384264391Snwhitehorn				ret += __puts("0x", putc, arg);
385264391Snwhitehorn			ret += __puts(s, putc, arg);
386264391Snwhitehorn			break;
387264391Snwhitehorn		case '0': case '1': case '2': case '3': case '4':
388264391Snwhitehorn		case '5': case '6': case '7': case '8': case '9':
389264391Snwhitehorn			pad = pad * 10 + c - '0';
390264391Snwhitehorn			goto reswitch;
391264391Snwhitehorn		default:
392264391Snwhitehorn			break;
393264391Snwhitehorn		}
394264391Snwhitehorn	}
395264391Snwhitehorn	return (ret);
396264391Snwhitehorn}
397264391Snwhitehorn
398264391Snwhitehornstatic int
399264391Snwhitehorn__sputc(char c, void *arg)
400264391Snwhitehorn{
401264391Snwhitehorn	struct sp_data *sp;
402264391Snwhitehorn
403264391Snwhitehorn	sp = arg;
404264391Snwhitehorn	if (sp->sp_len < sp->sp_size)
405264391Snwhitehorn		sp->sp_buf[sp->sp_len++] = c;
406264391Snwhitehorn	sp->sp_buf[sp->sp_len] = '\0';
407264391Snwhitehorn	return (1);
408264391Snwhitehorn}
409264391Snwhitehorn
410264391Snwhitehornstatic int
411264391Snwhitehorn__puts(const char *s, putc_func_t *putc, void *arg)
412264391Snwhitehorn{
413264391Snwhitehorn	const char *p;
414264391Snwhitehorn	int ret;
415264391Snwhitehorn
416264391Snwhitehorn	ret = 0;
417264391Snwhitehorn	for (p = s; *p != '\0'; p++)
418264391Snwhitehorn		ret += putc(*p, arg);
419264391Snwhitehorn	return (ret);
420264391Snwhitehorn}
421264391Snwhitehorn
422264391Snwhitehornstatic char *
423264391Snwhitehorn__uitoa(char *buf, u_int ui, int base)
424264391Snwhitehorn{
425264391Snwhitehorn	char *p;
426264391Snwhitehorn
427264391Snwhitehorn	p = buf;
428264391Snwhitehorn	*p = '\0';
429264391Snwhitehorn	do
430264391Snwhitehorn		*--p = digits[ui % base];
431264391Snwhitehorn	while ((ui /= base) != 0);
432264391Snwhitehorn	return (p);
433264391Snwhitehorn}
434264391Snwhitehorn
435264391Snwhitehornstatic char *
436264391Snwhitehorn__ultoa(char *buf, u_long ul, int base)
437264391Snwhitehorn{
438264391Snwhitehorn	char *p;
439264391Snwhitehorn
440264391Snwhitehorn	p = buf;
441264391Snwhitehorn	*p = '\0';
442264391Snwhitehorn	do
443264391Snwhitehorn		*--p = digits[ul % base];
444264391Snwhitehorn	while ((ul /= base) != 0);
445264391Snwhitehorn	return (p);
446264391Snwhitehorn}
447264391Snwhitehorn
448