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 static EFI_SYSTEM_TABLE *systab;
63 static EFI_HANDLE *image;
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), cols, rows, max_dim, best_mode;
113 EFI_DEVICE_PATH *devpath;
114 EFI_BOOT_SERVICES *BS;
115 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
116 SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
117 char *path = _PATH_LOADER;
122 BS = systab->BootServices;
123 status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
124 (VOID **)&ConsoleControl);
125 if (status == EFI_SUCCESS)
126 (void)ConsoleControl->SetMode(ConsoleControl,
127 EfiConsoleControlScreenText);
129 * Reset the console and find the best text mode.
131 conout = systab->ConOut;
132 conout->Reset(conout, TRUE);
133 max_dim = best_mode = 0;
135 status = conout->QueryMode(conout, i,
137 if (EFI_ERROR(status))
139 if (cols * rows > max_dim) {
140 max_dim = cols * rows;
145 conout->SetMode(conout, best_mode);
146 conout->EnableCursor(conout, TRUE);
147 conout->ClearScreen(conout);
150 ">> FreeBSD EFI boot block\n");
151 printf(" Loader path: %s\n", path);
153 status = systab->BootServices->LocateHandle(ByProtocol,
154 &BlockIoProtocolGUID, NULL, &nparts, handles);
155 nparts /= sizeof(handles[0]);
157 for (i = 0; i < nparts; i++) {
158 status = systab->BootServices->HandleProtocol(handles[i],
159 &DevicePathGUID, (void **)&devpath);
160 if (EFI_ERROR(status))
163 while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
164 devpath = NextDevicePathNode(devpath);
166 status = systab->BootServices->HandleProtocol(handles[i],
167 &BlockIoProtocolGUID, (void **)&blkio);
168 if (EFI_ERROR(status))
171 if (!blkio->Media->LogicalPartition)
174 if (domount(devpath, blkio, 1) >= 0)
179 panic("No bootable partition found");
181 bootdevhandle = handles[i];
184 panic("Load failed");
190 dskread(void *buf, u_int64_t lba, int nblk)
195 lba = lba / (bootdev->Media->BlockSize / DEV_BSIZE);
196 size = nblk * DEV_BSIZE;
197 status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
200 if (EFI_ERROR(status))
209 fsstat(ufs_ino_t inode)
212 static struct ufs1_dinode dp1;
216 static struct ufs2_dinode dp2;
219 static ufs_ino_t inomap;
222 size_t n, nb, size, off, vboff;
224 ufs2_daddr_t addr2, vbaddr;
225 static ufs2_daddr_t blkmap, indmap;
228 blkbuf = dmadat->blkbuf;
229 indbuf = dmadat->indbuf;
232 for (n = 0; sblock_try[n] != -1; n++) {
233 if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
234 SBLOCKSIZE / DEV_BSIZE))
236 memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
238 #if defined(UFS1_ONLY)
239 fs.fs_magic == FS_UFS1_MAGIC
240 #elif defined(UFS2_ONLY)
241 (fs.fs_magic == FS_UFS2_MAGIC &&
242 fs.fs_sblockloc == sblock_try[n])
244 fs.fs_magic == FS_UFS1_MAGIC ||
245 (fs.fs_magic == FS_UFS2_MAGIC &&
246 fs.fs_sblockloc == sblock_try[n])
249 fs.fs_bsize <= MAXBSIZE &&
250 fs.fs_bsize >= sizeof(struct fs))
253 if (sblock_try[n] == -1) {
259 memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
262 if (inomap != inode) {
264 if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
266 n = INO_TO_VBO(n, inode);
267 #if defined(UFS1_ONLY)
268 memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
269 sizeof(struct ufs1_dinode));
270 #elif defined(UFS2_ONLY)
271 memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
272 sizeof(struct ufs2_dinode));
274 if (fs.fs_magic == FS_UFS1_MAGIC)
275 memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
276 sizeof(struct ufs1_dinode));
278 memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
279 sizeof(struct ufs2_dinode));
290 static struct dmadat __dmadat;
293 domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
298 bootdevpath = device;
299 if (fsread(0, NULL, 0)) {
301 printf("domount: can't read superblock\n");
305 printf("Succesfully mounted UFS filesystem\n");
310 load(const char *fname)
314 EFI_HANDLE loaderhandle;
315 EFI_LOADED_IMAGE *loaded_image;
319 if ((ino = lookup(fname)) == 0) {
320 printf("File %s not found\n", fname);
324 bufsize = fsstat(ino);
325 status = systab->BootServices->AllocatePool(EfiLoaderData,
327 fsread(ino, buffer, bufsize);
329 /* XXX: For secure boot, we need our own loader here */
330 status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
331 buffer, bufsize, &loaderhandle);
332 if (EFI_ERROR(status))
333 printf("LoadImage failed with error %lx\n", status);
335 status = systab->BootServices->HandleProtocol(loaderhandle,
336 &LoadedImageGUID, (VOID**)&loaded_image);
337 if (EFI_ERROR(status))
338 printf("HandleProtocol failed with error %lx\n", status);
340 loaded_image->DeviceHandle = bootdevhandle;
342 status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
343 if (EFI_ERROR(status))
344 printf("StartImage failed with error %lx\n", status);
348 panic(const char *fmt, ...)
354 vsnprintf(buf, sizeof buf, fmt, ap);
355 printf("panic: %s\n", buf);
362 printf(const char *fmt, ...)
367 /* Don't annoy the user as we probe for partitions */
368 if (strcmp(fmt,"Not ufs\n") == 0)
372 ret = vprintf(fmt, ap);
378 putchar(char c, void *arg)
385 systab->ConOut->OutputString(systab->ConOut, buf);
389 systab->ConOut->OutputString(systab->ConOut, buf);
394 vprintf(const char *fmt, va_list ap)
398 ret = __printf(fmt, putchar, 0, ap);
403 vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
411 ret = __printf(fmt, __sputc, &sp, ap);
416 __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
418 char buf[(sizeof(long) * 8) + 1];
429 nbuf = &buf[sizeof buf - 1];
431 while ((c = *fmt++) != 0) {
439 reswitch: c = *fmt++;
445 ret += putc('%', arg);
453 ui = (u_int)va_arg(ap, int);
456 ret += putc('-', arg);
458 s = __uitoa(nbuf, ui, 10);
460 ul = (u_long)va_arg(ap, long);
463 ret += putc('-', arg);
465 s = __ultoa(nbuf, ul, 10);
467 ret += __puts(s, putc, arg);
474 ui = (u_int)va_arg(ap, u_int);
475 s = __uitoa(nbuf, ui, 8);
477 ul = (u_long)va_arg(ap, u_long);
478 s = __ultoa(nbuf, ul, 8);
480 ret += __puts(s, putc, arg);
483 ul = (u_long)va_arg(ap, void *);
484 s = __ultoa(nbuf, ul, 16);
485 ret += __puts("0x", putc, arg);
486 ret += __puts(s, putc, arg);
489 s = va_arg(ap, char *);
490 ret += __puts(s, putc, arg);
494 ui = va_arg(ap, u_int);
495 s = __uitoa(nbuf, ui, 10);
497 ul = va_arg(ap, u_long);
498 s = __ultoa(nbuf, ul, 10);
500 ret += __puts(s, putc, arg);
504 ui = va_arg(ap, u_int);
505 s = __uitoa(nbuf, ui, 16);
507 ul = va_arg(ap, u_long);
508 s = __ultoa(nbuf, ul, 16);
511 ret += __puts("0x", putc, arg);
512 ret += __puts(s, putc, arg);
514 case '0': case '1': case '2': case '3': case '4':
515 case '5': case '6': case '7': case '8': case '9':
516 pad = pad * 10 + c - '0';
526 __sputc(char c, void *arg)
531 if (sp->sp_len < sp->sp_size)
532 sp->sp_buf[sp->sp_len++] = c;
533 sp->sp_buf[sp->sp_len] = '\0';
538 __puts(const char *s, putc_func_t *putc, void *arg)
544 for (p = s; *p != '\0'; p++)
545 ret += putc(*p, arg);
550 __uitoa(char *buf, u_int ui, int base)
557 *--p = digits[ui % base];
558 while ((ui /= base) != 0);
563 __ultoa(char *buf, u_long ul, int base)
570 *--p = digits[ul % base];
571 while ((ul /= base) != 0);