2 * Copyright (c) 1998 Robert Nordier
4 * Copyright (c) 2001 Robert Drehmel
6 * Copyright (c) 2014 Nathan Whitehorn
9 * Redistribution and use in source and binary forms are freely
10 * permitted provided that the above copyright notice and this
11 * paragraph and the following disclaimer are duplicated in all
14 * This software is provided "AS IS" and without any express or
15 * implied warranties, including, without limitation, the implied
16 * warranties of merchantability and fitness for a particular
20 #include <sys/cdefs.h>
21 __FBSDID("$FreeBSD$");
23 #include <sys/param.h>
24 #include <sys/dirent.h>
25 #include <machine/elf.h>
26 #include <machine/stdarg.h>
29 #include <eficonsctl.h>
31 #define _PATH_LOADER "/boot/loader.efi"
32 #define _PATH_KERNEL "/boot/kernel/kernel"
34 #define BSIZEMAX 16384
36 typedef int putc_func_t(char c, void *arg);
44 static const char digits[] = "0123456789abcdef";
46 static void panic(const char *fmt, ...) __dead2;
47 static int printf(const char *fmt, ...);
48 static int putchar(char c, void *arg);
49 static int vprintf(const char *fmt, va_list ap);
50 static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
52 static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
53 static int __putc(char c, void *arg);
54 static int __puts(const char *s, putc_func_t *putc, void *arg);
55 static int __sputc(char c, void *arg);
56 static char *__uitoa(char *buf, u_int val, int base);
57 static char *__ultoa(char *buf, u_long val, int base);
59 static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
60 static void load(const char *fname);
62 EFI_SYSTEM_TABLE *systab;
66 bcopy(const void *src, void *dst, size_t len)
76 memcpy(void *dst, const void *src, size_t len)
82 bzero(void *b, size_t len)
91 strcmp(const char *s1, const char *s2)
93 for (; *s1 == *s2 && *s1; s1++, s2++)
95 return ((u_char)*s1 - (u_char)*s2);
98 static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
99 static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
100 static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
101 static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
103 static EFI_BLOCK_IO *bootdev;
104 static EFI_DEVICE_PATH *bootdevpath;
105 static EFI_HANDLE *bootdevhandle;
107 EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
109 EFI_HANDLE handles[128];
111 UINTN i, nparts = sizeof(handles);
113 EFI_DEVICE_PATH *devpath;
114 EFI_BOOT_SERVICES *BS;
115 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
116 char *path = _PATH_LOADER;
121 BS = systab->BootServices;
122 status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
123 (VOID **)&ConsoleControl);
124 if (status == EFI_SUCCESS)
125 (void)ConsoleControl->SetMode(ConsoleControl,
126 EfiConsoleControlScreenText);
128 printf(" \n>> FreeBSD EFI boot block\n");
129 printf(" Loader path: %s\n", path);
131 status = systab->BootServices->LocateHandle(ByProtocol,
132 &BlockIoProtocolGUID, NULL, &nparts, handles);
133 nparts /= sizeof(handles[0]);
135 for (i = 0; i < nparts; i++) {
136 status = systab->BootServices->HandleProtocol(handles[i],
137 &DevicePathGUID, (void **)&devpath);
138 if (EFI_ERROR(status))
141 while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
142 devpath = NextDevicePathNode(devpath);
144 status = systab->BootServices->HandleProtocol(handles[i],
145 &BlockIoProtocolGUID, (void **)&blkio);
146 if (EFI_ERROR(status))
149 if (!blkio->Media->LogicalPartition)
152 if (domount(devpath, blkio, 1) >= 0)
157 panic("No bootable partition found");
159 bootdevhandle = handles[i];
162 panic("Load failed");
168 dskread(void *buf, u_int64_t lba, int nblk)
173 lba = lba / (bootdev->Media->BlockSize / DEV_BSIZE);
174 size = nblk * DEV_BSIZE;
175 status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
178 if (EFI_ERROR(status))
187 fsstat(ufs_ino_t inode)
190 static struct ufs1_dinode dp1;
194 static struct ufs2_dinode dp2;
197 static ufs_ino_t inomap;
200 size_t n, nb, size, off, vboff;
202 ufs2_daddr_t addr2, vbaddr;
203 static ufs2_daddr_t blkmap, indmap;
206 blkbuf = dmadat->blkbuf;
207 indbuf = dmadat->indbuf;
210 for (n = 0; sblock_try[n] != -1; n++) {
211 if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
212 SBLOCKSIZE / DEV_BSIZE))
214 memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
216 #if defined(UFS1_ONLY)
217 fs.fs_magic == FS_UFS1_MAGIC
218 #elif defined(UFS2_ONLY)
219 (fs.fs_magic == FS_UFS2_MAGIC &&
220 fs.fs_sblockloc == sblock_try[n])
222 fs.fs_magic == FS_UFS1_MAGIC ||
223 (fs.fs_magic == FS_UFS2_MAGIC &&
224 fs.fs_sblockloc == sblock_try[n])
227 fs.fs_bsize <= MAXBSIZE &&
228 fs.fs_bsize >= sizeof(struct fs))
231 if (sblock_try[n] == -1) {
237 memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
240 if (inomap != inode) {
242 if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
244 n = INO_TO_VBO(n, inode);
245 #if defined(UFS1_ONLY)
246 memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
247 sizeof(struct ufs1_dinode));
248 #elif defined(UFS2_ONLY)
249 memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
250 sizeof(struct ufs2_dinode));
252 if (fs.fs_magic == FS_UFS1_MAGIC)
253 memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
254 sizeof(struct ufs1_dinode));
256 memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
257 sizeof(struct ufs2_dinode));
268 static struct dmadat __dmadat;
271 domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
276 bootdevpath = device;
277 if (fsread(0, NULL, 0)) {
279 printf("domount: can't read superblock\n");
283 printf("Succesfully mounted UFS filesystem\n");
288 load(const char *fname)
292 EFI_HANDLE loaderhandle;
293 EFI_LOADED_IMAGE *loaded_image;
297 if ((ino = lookup(fname)) == 0) {
298 printf("File %s not found\n", fname);
302 bufsize = fsstat(ino);
303 status = systab->BootServices->AllocatePool(EfiLoaderData,
305 fsread(ino, buffer, bufsize);
307 /* XXX: For secure boot, we need our own loader here */
308 status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
309 buffer, bufsize, &loaderhandle);
311 status = systab->BootServices->HandleProtocol(loaderhandle,
312 &LoadedImageGUID, (VOID**)&loaded_image);
313 loaded_image->DeviceHandle = bootdevhandle;
315 status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
319 panic(const char *fmt, ...)
325 vsnprintf(buf, sizeof buf, fmt, ap);
326 printf("panic: %s\n", buf);
333 printf(const char *fmt, ...)
338 /* Don't annoy the user as we probe for partitions */
339 if (strcmp(fmt,"Not ufs\n") == 0)
343 ret = vprintf(fmt, ap);
349 putchar(char c, void *arg)
356 systab->ConOut->OutputString(systab->ConOut, buf);
360 systab->ConOut->OutputString(systab->ConOut, buf);
365 vprintf(const char *fmt, va_list ap)
369 ret = __printf(fmt, putchar, 0, ap);
374 vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
382 ret = __printf(fmt, __sputc, &sp, ap);
387 __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
389 char buf[(sizeof(long) * 8) + 1];
400 nbuf = &buf[sizeof buf - 1];
402 while ((c = *fmt++) != 0) {
410 reswitch: c = *fmt++;
416 ret += putc('%', arg);
424 ui = (u_int)va_arg(ap, int);
427 ret += putc('-', arg);
429 s = __uitoa(nbuf, ui, 10);
431 ul = (u_long)va_arg(ap, long);
434 ret += putc('-', arg);
436 s = __ultoa(nbuf, ul, 10);
438 ret += __puts(s, putc, arg);
445 ui = (u_int)va_arg(ap, u_int);
446 s = __uitoa(nbuf, ui, 8);
448 ul = (u_long)va_arg(ap, u_long);
449 s = __ultoa(nbuf, ul, 8);
451 ret += __puts(s, putc, arg);
454 ul = (u_long)va_arg(ap, void *);
455 s = __ultoa(nbuf, ul, 16);
456 ret += __puts("0x", putc, arg);
457 ret += __puts(s, putc, arg);
460 s = va_arg(ap, char *);
461 ret += __puts(s, putc, arg);
465 ui = va_arg(ap, u_int);
466 s = __uitoa(nbuf, ui, 10);
468 ul = va_arg(ap, u_long);
469 s = __ultoa(nbuf, ul, 10);
471 ret += __puts(s, putc, arg);
475 ui = va_arg(ap, u_int);
476 s = __uitoa(nbuf, ui, 16);
478 ul = va_arg(ap, u_long);
479 s = __ultoa(nbuf, ul, 16);
482 ret += __puts("0x", putc, arg);
483 ret += __puts(s, putc, arg);
485 case '0': case '1': case '2': case '3': case '4':
486 case '5': case '6': case '7': case '8': case '9':
487 pad = pad * 10 + c - '0';
497 __sputc(char c, void *arg)
502 if (sp->sp_len < sp->sp_size)
503 sp->sp_buf[sp->sp_len++] = c;
504 sp->sp_buf[sp->sp_len] = '\0';
509 __puts(const char *s, putc_func_t *putc, void *arg)
515 for (p = s; *p != '\0'; p++)
516 ret += putc(*p, arg);
521 __uitoa(char *buf, u_int ui, int base)
528 *--p = digits[ui % base];
529 while ((ui /= base) != 0);
534 __ultoa(char *buf, u_long ul, int base)
541 *--p = digits[ul % base];
542 while ((ul /= base) != 0);