Changeset View
Standalone View
sys/boot/efi/boot1/boot1.c
/*- | /*- | ||||
* Copyright (c) 1998 Robert Nordier | * Copyright (c) 1998 Robert Nordier | ||||
* All rights reserved. | * All rights reserved. | ||||
* Copyright (c) 2001 Robert Drehmel | * Copyright (c) 2001 Robert Drehmel | ||||
* All rights reserved. | * All rights reserved. | ||||
* Copyright (c) 2014 Nathan Whitehorn | * Copyright (c) 2014 Nathan Whitehorn | ||||
* All rights reserved. | * All rights reserved. | ||||
* Copyright (c) 2015 Eric McCorkle | |||||
* All rights reserved. | |||||
dim: s/reverved/reserved/ | |||||
* | * | ||||
* Redistribution and use in source and binary forms are freely | * Redistribution and use in source and binary forms are freely | ||||
* permitted provided that the above copyright notice and this | * permitted provided that the above copyright notice and this | ||||
* paragraph and the following disclaimer are duplicated in all | * paragraph and the following disclaimer are duplicated in all | ||||
* such forms. | * such forms. | ||||
* | * | ||||
* This software is provided "AS IS" and without any express or | * This software is provided "AS IS" and without any express or | ||||
* implied warranties, including, without limitation, the implied | * implied warranties, including, without limitation, the implied | ||||
* warranties of merchantability and fitness for a particular | * warranties of merchantability and fitness for a particular | ||||
* purpose. | * purpose. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/dirent.h> | |||||
#include <machine/elf.h> | #include <machine/elf.h> | ||||
#include <machine/stdarg.h> | #include <machine/stdarg.h> | ||||
#include <efi.h> | #include <efi.h> | ||||
#include <eficonsctl.h> | #include <eficonsctl.h> | ||||
#include "boot_module.h" | |||||
#define _PATH_LOADER "/boot/loader.efi" | #define _PATH_LOADER "/boot/loader.efi" | ||||
#define _PATH_KERNEL "/boot/kernel/kernel" | |||||
#define BSIZEMAX 16384 | #ifdef EFI_DEBUG | ||||
#define DPRINTF(fmt, args...) \ | |||||
do { \ | |||||
printf(fmt, ##args) \ | |||||
} while (0) | |||||
#else | |||||
#define DPRINTF(fmt, args...) {} | |||||
#endif | |||||
typedef int putc_func_t(char c, void *arg); | typedef int putc_func_t(char c, void *arg); | ||||
struct sp_data { | struct sp_data { | ||||
char *sp_buf; | char *sp_buf; | ||||
u_int sp_len; | u_int sp_len; | ||||
u_int sp_size; | u_int sp_size; | ||||
}; | }; | ||||
static const char digits[] = "0123456789abcdef"; | static const boot_module_t *boot_modules[] = | ||||
{ | |||||
#ifdef EFI_ZFS_BOOT | |||||
&zfs_module, | |||||
#endif | |||||
#ifdef EFI_UFS_BOOT | |||||
&ufs_module | |||||
#endif | |||||
}; | |||||
static void panic(const char *fmt, ...) __dead2; | #define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*)) | ||||
static int printf(const char *fmt, ...); | /* The initial number of handles used to query EFI for partitions. */ | ||||
static int putchar(char c, void *arg); | #define NUM_HANDLES_INIT 24 | ||||
static int vprintf(const char *fmt, va_list ap); | |||||
static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); | |||||
static const char digits[] = "0123456789abcdef"; | |||||
static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); | static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); | ||||
static int __putc(char c, void *arg); | |||||
static int __puts(const char *s, putc_func_t *putc, void *arg); | static int __puts(const char *s, putc_func_t *putc, void *arg); | ||||
static int __sputc(char c, void *arg); | static int __sputc(char c, void *arg); | ||||
static char *__uitoa(char *buf, u_int val, int base); | static char *__uitoa(char *buf, u_int val, int base); | ||||
static char *__ultoa(char *buf, u_long val, int base); | static char *__ultoa(char *buf, u_long val, int base); | ||||
static int putchr(char c, void *arg); | |||||
static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet); | static void try_load(const boot_module_t* mod); | ||||
static void load(const char *fname); | static EFI_STATUS probe_handle(EFI_HANDLE h); | ||||
static EFI_SYSTEM_TABLE *systab; | EFI_SYSTEM_TABLE *systab; | ||||
EFI_BOOT_SERVICES *bs; | |||||
static EFI_HANDLE *image; | static EFI_HANDLE *image; | ||||
static void | void * | ||||
Malloc(size_t len, const char *file, int line) | |||||
emasteUnsubmitted Done Inline ActionsWhat's this capital-M Malloc used for? emaste: What's this capital-M Malloc used for? | |||||
smhAuthorUnsubmitted Done Inline ActionsWithout it build fails with: --- boot1.efi --- if [ `objdump -t boot1.sym | fgrep '*UND*' | wc -l` != 0 ]; then objdump -t boot1.sym | fgrep '*UND*'; exit 1; fi 0000000000000000 *UND* 0000000000000000 Malloc smh: Without it build fails with:
```
--- boot1.efi ---
if [ `objdump -t boot1.sym | fgrep '*UND*' |… | |||||
Done Inline ActionsOh, required by the ZFS module I guess? emaste: Oh, required by the ZFS module I guess? | |||||
Done Inline Actionszfs.c and zfsimp.c both use malloc so yer that will be it. smh: zfs.c and zfsimp.c both use malloc so yer that will be it. | |||||
Done Inline ActionsMalloc() is usually provided by libstand iianm. allanjude: Malloc() is usually provided by libstand iianm. | |||||
Done Inline Actionsboot1 doesn't use libstand. andrew: boot1 doesn't use libstand. | |||||
Done Inline ActionsFor some arches it actually does e.g. i386, I'm currently testing to see if its worth using on all platforms to eliminate the custom string / memory functions. smh: For some arches it actually does e.g. i386, I'm currently testing to see if its worth using on… | |||||
Done Inline ActionsThe issue (and the reason the original boot1.efi provided its own versions of some functions) is that boot1 has to be compiled for the EFI (win32) ABI, unlike the rest of the system. eric_metricspace.net: The issue (and the reason the original boot1.efi provided its own versions of some functions)… | |||||
{ | |||||
void *out; | |||||
if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS) | |||||
return (out); | |||||
return (NULL); | |||||
} | |||||
char * | |||||
strcpy(char * __restrict to, const char * __restrict from) | |||||
emasteUnsubmitted Done Inline Actionscan we link against libstand for these? emaste: can we link against libstand for these? | |||||
smhAuthorUnsubmitted Done Inline ActionsI tried that but it got ugly quickly unfortunately, so not without significant extra work smh: I tried that but it got ugly quickly unfortunately, so not without significant extra work | |||||
{ | |||||
char *save = to; | |||||
for (; (*to = *from) != 0; ++from, ++to); | |||||
return (save); | |||||
} | |||||
char * | |||||
strchr(const char *s, int c) | |||||
{ | |||||
int i; | |||||
for (i = 0; s[i]; i++) | |||||
if (s[i] == c) | |||||
return ((char*)(s + i)); | |||||
return (NULL); | |||||
} | |||||
int | |||||
strncmp(const char *s1, const char *s2, size_t n) | |||||
{ | |||||
if (n == 0) | |||||
return (0); | |||||
do { | |||||
if (*s1 != *s2++) | |||||
return (*(const unsigned char *)s1 - | |||||
*(const unsigned char *)(s2 - 1)); | |||||
if (*s1++ == '\0') | |||||
break; | |||||
} while (--n != 0); | |||||
return (0); | |||||
} | |||||
size_t | |||||
strlen(const char *s) | |||||
{ | |||||
size_t len = 0; | |||||
for (; *s != '\0'; s++, len++) | |||||
; | |||||
return (len); | |||||
} | |||||
char * | |||||
strdup(const char *s) | |||||
{ | |||||
size_t len; | |||||
char *out; | |||||
len = strlen(s) + 1; | |||||
out = malloc(len); | |||||
if (out == NULL) | |||||
return (NULL); | |||||
bcopy(s, out, len); | |||||
return (out); | |||||
} | |||||
int | |||||
bcmp(const void *a, const void *b, size_t len) | |||||
{ | |||||
const char *sa = a; | |||||
const char *sb = b; | |||||
int i; | |||||
for (i = 0; i < len; i++) | |||||
if (sa[i] != sb[i]) | |||||
return (1); | |||||
return (0); | |||||
} | |||||
int | |||||
memcmp(const void *a, const void *b, size_t len) | |||||
{ | |||||
return bcmp(a, b, len); | |||||
} | |||||
void | |||||
bcopy(const void *src, void *dst, size_t len) | bcopy(const void *src, void *dst, size_t len) | ||||
{ | { | ||||
const char *s = src; | const char *s = src; | ||||
char *d = dst; | char *d = dst; | ||||
while (len-- != 0) | while (len-- != 0) | ||||
*d++ = *s++; | *d++ = *s++; | ||||
} | } | ||||
static void | void * | ||||
memcpy(void *dst, const void *src, size_t len) | memcpy(void *dst, const void *src, size_t len) | ||||
Not Done Inline ActionsI've just updated to use libstand, which was a dependency for some arches anyway, so it would be good if you could confirm this works as expected where you thought this was an issue Eric. I have confirmed using qemu on amd64 that all is good. smh: I've just updated to use libstand, which was a dependency for some arches anyway, so it would… | |||||
{ | { | ||||
bcopy(src, dst, len); | bcopy(src, dst, len); | ||||
return (dst); | |||||
} | } | ||||
static void | void * | ||||
bzero(void *b, size_t len) | memset(void *b, int val, size_t len) | ||||
{ | { | ||||
char *p = b; | char *p = b; | ||||
while (len-- != 0) | while (len-- != 0) | ||||
*p++ = 0; | *p++ = val; | ||||
return (b); | |||||
} | } | ||||
static int | int | ||||
strcmp(const char *s1, const char *s2) | strcmp(const char *s1, const char *s2) | ||||
Not Done Inline ActionsThis is now done, the problem cause was the image size. smh: This is now done, the problem cause was the image size. | |||||
{ | { | ||||
for (; *s1 == *s2 && *s1; s1++, s2++) | for (; *s1 == *s2 && *s1; s1++, s2++) | ||||
; | ; | ||||
return ((u_char)*s1 - (u_char)*s2); | return ((u_char)*s1 - (u_char)*s2); | ||||
} | } | ||||
static int | |||||
putchr(char c, void *arg) | |||||
{ | |||||
CHAR16 buf[2]; | |||||
if (c == '\n') | |||||
putchr('\r', arg); | |||||
buf[0] = c; | |||||
buf[1] = 0; | |||||
systab->ConOut->OutputString(systab->ConOut, buf); | |||||
return (1); | |||||
} | |||||
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; | static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; | ||||
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; | static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; | ||||
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL; | static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL; | ||||
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; | static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; | ||||
static EFI_BLOCK_IO *bootdev; | /* | ||||
static EFI_DEVICE_PATH *bootdevpath; | * This function only returns if it fails to load the kernel. If it | ||||
static EFI_HANDLE *bootdevhandle; | * succeeds, it simply boots the kernel. | ||||
*/ | |||||
void | |||||
try_load(const boot_module_t *mod) | |||||
{ | |||||
size_t bufsize; | |||||
void *buf; | |||||
dev_info_t *dev; | |||||
EFI_HANDLE loaderhandle; | |||||
EFI_LOADED_IMAGE *loaded_image; | |||||
EFI_STATUS status; | |||||
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) | status = mod->load(_PATH_LOADER, &dev, &buf, &bufsize); | ||||
if (status == EFI_NOT_FOUND) | |||||
return; | |||||
if (status != EFI_SUCCESS) { | |||||
printf("%s failed to load %s (%lu)\n", mod->name, _PATH_LOADER, | |||||
EFI_ERROR_CODE(status)); | |||||
return; | |||||
} | |||||
if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize, | |||||
&loaderhandle)) != EFI_SUCCESS) { | |||||
printf("Failed to load image provided by %s (%lu)\n", mod->name, | |||||
EFI_ERROR_CODE(status)); | |||||
return; | |||||
} | |||||
if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID, | |||||
(VOID**)&loaded_image)) != EFI_SUCCESS) { | |||||
printf("Failed to query LoadedImage provided by %s (%lu)\n", | |||||
mod->name, EFI_ERROR_CODE(status)); | |||||
return; | |||||
} | |||||
loaded_image->DeviceHandle = dev->devhandle; | |||||
if ((status = bs->StartImage(loaderhandle, NULL, NULL)) != | |||||
EFI_SUCCESS) { | |||||
printf("Failed start image provided by %s (%lu)\n", mod->name, | |||||
EFI_ERROR_CODE(status)); | |||||
return; | |||||
} | |||||
} | |||||
void | |||||
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) | |||||
{ | { | ||||
EFI_HANDLE handles[128]; | EFI_HANDLE *handles; | ||||
EFI_BLOCK_IO *blkio; | |||||
UINTN i, nparts = sizeof(handles), cols, rows, max_dim, best_mode; | |||||
EFI_STATUS status; | EFI_STATUS status; | ||||
EFI_DEVICE_PATH *devpath; | |||||
EFI_BOOT_SERVICES *BS; | |||||
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; | EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; | ||||
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; | SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; | ||||
char *path = _PATH_LOADER; | UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; | ||||
/* Basic initialization*/ | |||||
systab = Xsystab; | systab = Xsystab; | ||||
image = Ximage; | image = Ximage; | ||||
bs = Xsystab->BootServices; | |||||
BS = systab->BootServices; | /* Set up the console, so printf works. */ | ||||
status = BS->LocateProtocol(&ConsoleControlGUID, NULL, | status = bs->LocateProtocol(&ConsoleControlGUID, NULL, | ||||
(VOID **)&ConsoleControl); | (VOID **)&ConsoleControl); | ||||
if (status == EFI_SUCCESS) | if (status == EFI_SUCCESS) | ||||
(void)ConsoleControl->SetMode(ConsoleControl, | (void)ConsoleControl->SetMode(ConsoleControl, | ||||
EfiConsoleControlScreenText); | EfiConsoleControlScreenText); | ||||
/* | /* | ||||
* Reset the console and find the best text mode. | * Reset the console and find the best text mode. | ||||
*/ | */ | ||||
conout = systab->ConOut; | conout = systab->ConOut; | ||||
conout->Reset(conout, TRUE); | conout->Reset(conout, TRUE); | ||||
max_dim = best_mode = 0; | max_dim = best_mode = 0; | ||||
for (i = 0; ; i++) { | for (i = 0; ; i++) { | ||||
status = conout->QueryMode(conout, i, | status = conout->QueryMode(conout, i, &cols, &rows); | ||||
&cols, &rows); | |||||
if (EFI_ERROR(status)) | if (EFI_ERROR(status)) | ||||
break; | break; | ||||
if (cols * rows > max_dim) { | if (cols * rows > max_dim) { | ||||
max_dim = cols * rows; | max_dim = cols * rows; | ||||
best_mode = i; | best_mode = i; | ||||
} | } | ||||
} | } | ||||
if (max_dim > 0) | if (max_dim > 0) | ||||
conout->SetMode(conout, best_mode); | conout->SetMode(conout, best_mode); | ||||
conout->EnableCursor(conout, TRUE); | conout->EnableCursor(conout, TRUE); | ||||
conout->ClearScreen(conout); | conout->ClearScreen(conout); | ||||
printf("\n" | printf("\n>> FreeBSD EFI boot block\n"); | ||||
">> FreeBSD EFI boot block\n"); | printf(" Loader path: %s\n\n", _PATH_LOADER); | ||||
printf(" Loader path: %s\n", path); | printf(" Initializing modules:"); | ||||
for (i = 0; i < NUM_BOOT_MODULES; i++) { | |||||
status = systab->BootServices->LocateHandle(ByProtocol, | if (boot_modules[i] == NULL) | ||||
&BlockIoProtocolGUID, NULL, &nparts, handles); | |||||
nparts /= sizeof(handles[0]); | |||||
for (i = 0; i < nparts; i++) { | |||||
status = systab->BootServices->HandleProtocol(handles[i], | |||||
&DevicePathGUID, (void **)&devpath); | |||||
if (EFI_ERROR(status)) | |||||
continue; | continue; | ||||
while (!IsDevicePathEnd(NextDevicePathNode(devpath))) | printf(" %s", boot_modules[i]->name); | ||||
devpath = NextDevicePathNode(devpath); | if (boot_modules[i]->init != NULL) | ||||
boot_modules[i]->init(); | |||||
} | |||||
putchr('\n', NULL); | |||||
status = systab->BootServices->HandleProtocol(handles[i], | /* Get all the device handles */ | ||||
&BlockIoProtocolGUID, (void **)&blkio); | hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE); | ||||
if (EFI_ERROR(status)) | if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles)) | ||||
continue; | != EFI_SUCCESS) | ||||
panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT, | |||||
EFI_ERROR_CODE(status)); | |||||
if (!blkio->Media->LogicalPartition) | status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, | ||||
continue; | &hsize, handles); | ||||
switch (status) { | |||||
case EFI_SUCCESS: | |||||
break; | |||||
case EFI_BUFFER_TOO_SMALL: | |||||
(void)bs->FreePool(handles); | |||||
if ((status = bs->AllocatePool(EfiLoaderData, hsize, | |||||
(void **)&handles) != EFI_SUCCESS)) { | |||||
panic("Failed to allocate %lu handles (%lu)", hsize / | |||||
sizeof(*handles), status); | |||||
} | |||||
status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, | |||||
NULL, &hsize, handles); | |||||
if (status != EFI_SUCCESS) | |||||
panic("Failed to get device handles (%lu)\n", | |||||
EFI_ERROR_CODE(status)); | |||||
break; | |||||
default: | |||||
panic("Failed to get device handles (%lu)", | |||||
EFI_ERROR_CODE(status)); | |||||
} | |||||
if (domount(devpath, blkio, 1) >= 0) | /* Scan all partitions, probing with all modules. */ | ||||
nhandles = hsize / sizeof(*handles); | |||||
printf(" Probing %lu block devices...", nhandles); | |||||
for (i = 0; i < nhandles; i++) { | |||||
status = probe_handle(handles[i]); | |||||
switch (status) { | |||||
case EFI_UNSUPPORTED: | |||||
printf("."); | |||||
break; | break; | ||||
case EFI_SUCCESS: | |||||
printf("+"); | |||||
break; | |||||
default: | |||||
printf("x"); | |||||
break; | |||||
} | } | ||||
} | |||||
printf(" done\n"); | |||||
if (i == nparts) | /* Status summary. */ | ||||
panic("No bootable partition found"); | for (i = 0; i < NUM_BOOT_MODULES; i++) { | ||||
if (boot_modules[i] != NULL) { | |||||
printf(" "); | |||||
boot_modules[i]->status(); | |||||
} | |||||
} | |||||
bootdevhandle = handles[i]; | /* Select a partition to boot by trying each module in order. */ | ||||
load(path); | for (i = 0; i < NUM_BOOT_MODULES; i++) | ||||
if (boot_modules[i] != NULL) | |||||
try_load(boot_modules[i]); | |||||
panic("Load failed"); | /* If we get here, we're out of luck... */ | ||||
panic("No bootable partitions found!"); | |||||
return EFI_SUCCESS; | |||||
} | } | ||||
Not Done Inline ActionsInstead I think we want to print the message, delay (5 seconds?) and then exit the EFI application. But that can happen in a separate change. emaste: Instead I think we want to print the message, delay (5 seconds?) and then exit the EFI… | |||||
Not Done Inline Actionssounds good. smh: sounds good. | |||||
static int | static EFI_STATUS | ||||
dskread(void *buf, u_int64_t lba, int nblk) | probe_handle(EFI_HANDLE h) | ||||
{ | { | ||||
dev_info_t *devinfo; | |||||
EFI_BLOCK_IO *blkio; | |||||
EFI_DEVICE_PATH *devpath; | |||||
EFI_STATUS status; | EFI_STATUS status; | ||||
int size; | UINTN i; | ||||
lba = lba / (bootdev->Media->BlockSize / DEV_BSIZE); | /* Figure out if we're dealing with an actual partition. */ | ||||
size = nblk * DEV_BSIZE; | status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); | ||||
status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba, | if (status == EFI_UNSUPPORTED) | ||||
size, buf); | return (status); | ||||
if (EFI_ERROR(status)) | if (status != EFI_SUCCESS) { | ||||
return (-1); | DPRINTF("\nFailed to query DevicePath (%lu)\n", | ||||
EFI_ERROR_CODE(status)); | |||||
return (0); | return (status); | ||||
} | } | ||||
#include "ufsread.c" | while (!IsDevicePathEnd(NextDevicePathNode(devpath))) | ||||
devpath = NextDevicePathNode(devpath); | |||||
static ssize_t | status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); | ||||
fsstat(ufs_ino_t inode) | if (status == EFI_UNSUPPORTED) | ||||
{ | return (status); | ||||
#ifndef UFS2_ONLY | |||||
static struct ufs1_dinode dp1; | |||||
ufs1_daddr_t addr1; | |||||
#endif | |||||
#ifndef UFS1_ONLY | |||||
static struct ufs2_dinode dp2; | |||||
#endif | |||||
static struct fs fs; | |||||
static ufs_ino_t inomap; | |||||
char *blkbuf; | |||||
void *indbuf; | |||||
size_t n, nb, size, off, vboff; | |||||
ufs_lbn_t lbn; | |||||
ufs2_daddr_t addr2, vbaddr; | |||||
static ufs2_daddr_t blkmap, indmap; | |||||
u_int u; | |||||
blkbuf = dmadat->blkbuf; | if (status != EFI_SUCCESS) { | ||||
indbuf = dmadat->indbuf; | DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", | ||||
if (!dsk_meta) { | EFI_ERROR_CODE(status)); | ||||
inomap = 0; | return (status); | ||||
for (n = 0; sblock_try[n] != -1; n++) { | |||||
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE, | |||||
SBLOCKSIZE / DEV_BSIZE)) | |||||
return -1; | |||||
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); | |||||
if (( | |||||
#if defined(UFS1_ONLY) | |||||
fs.fs_magic == FS_UFS1_MAGIC | |||||
#elif defined(UFS2_ONLY) | |||||
(fs.fs_magic == FS_UFS2_MAGIC && | |||||
fs.fs_sblockloc == sblock_try[n]) | |||||
#else | |||||
fs.fs_magic == FS_UFS1_MAGIC || | |||||
(fs.fs_magic == FS_UFS2_MAGIC && | |||||
fs.fs_sblockloc == sblock_try[n]) | |||||
#endif | |||||
) && | |||||
fs.fs_bsize <= MAXBSIZE && | |||||
fs.fs_bsize >= sizeof(struct fs)) | |||||
break; | |||||
} | } | ||||
if (sblock_try[n] == -1) { | |||||
printf("Not ufs\n"); | |||||
return -1; | |||||
} | |||||
dsk_meta++; | |||||
} else | |||||
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); | |||||
if (!inode) | |||||
return 0; | |||||
if (inomap != inode) { | |||||
n = IPERVBLK(&fs); | |||||
if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK)) | |||||
return -1; | |||||
n = INO_TO_VBO(n, inode); | |||||
#if defined(UFS1_ONLY) | |||||
memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, | |||||
sizeof(struct ufs1_dinode)); | |||||
#elif defined(UFS2_ONLY) | |||||
memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, | |||||
sizeof(struct ufs2_dinode)); | |||||
#else | |||||
if (fs.fs_magic == FS_UFS1_MAGIC) | |||||
memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, | |||||
sizeof(struct ufs1_dinode)); | |||||
else | |||||
memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, | |||||
sizeof(struct ufs2_dinode)); | |||||
#endif | |||||
inomap = inode; | |||||
fs_off = 0; | |||||
blkmap = indmap = 0; | |||||
} | |||||
size = DIP(di_size); | |||||
n = size - fs_off; | |||||
return (n); | |||||
} | |||||
static struct dmadat __dmadat; | if (!blkio->Media->LogicalPartition) | ||||
return (EFI_UNSUPPORTED); | |||||
static int | /* Run through each module, see if it can load this partition */ | ||||
domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet) | for (i = 0; i < NUM_BOOT_MODULES; i++ ) { | ||||
{ | if (boot_modules[i] == NULL) | ||||
continue; | |||||
dmadat = &__dmadat; | if ((status = bs->AllocatePool(EfiLoaderData, | ||||
bootdev = blkio; | sizeof(*devinfo), (void **)&devinfo)) != | ||||
bootdevpath = device; | EFI_SUCCESS) { | ||||
if (fsread(0, NULL, 0)) { | DPRINTF("\nFailed to allocate devinfo (%lu)\n", | ||||
if (!quiet) | EFI_ERROR_CODE(status)); | ||||
printf("domount: can't read superblock\n"); | continue; | ||||
return (-1); | |||||
} | } | ||||
if (!quiet) | devinfo->dev = blkio; | ||||
printf("Succesfully mounted UFS filesystem\n"); | devinfo->devpath = devpath; | ||||
return (0); | devinfo->devhandle = h; | ||||
devinfo->devdata = NULL; | |||||
devinfo->next = NULL; | |||||
status = boot_modules[i]->probe(devinfo); | |||||
if (status == EFI_SUCCESS) | |||||
return (EFI_SUCCESS); | |||||
(void)bs->FreePool(devinfo); | |||||
} | } | ||||
static void | return (EFI_UNSUPPORTED); | ||||
load(const char *fname) | } | ||||
void | |||||
add_device(dev_info_t **devinfop, dev_info_t *devinfo) | |||||
{ | { | ||||
ufs_ino_t ino; | dev_info_t *dev; | ||||
EFI_STATUS status; | |||||
EFI_HANDLE loaderhandle; | |||||
EFI_LOADED_IMAGE *loaded_image; | |||||
void *buffer; | |||||
size_t bufsize; | |||||
Done Inline Actionstrailing whitespace emaste: trailing whitespace | |||||
if ((ino = lookup(fname)) == 0) { | if (*devinfop == NULL) { | ||||
printf("File %s not found\n", fname); | *devinfop = devinfo; | ||||
return; | return; | ||||
} | } | ||||
bufsize = fsstat(ino); | for (dev = *devinfop; dev->next != NULL; dev = dev->next) | ||||
status = systab->BootServices->AllocatePool(EfiLoaderData, | ; | ||||
bufsize, &buffer); | |||||
fsread(ino, buffer, bufsize); | |||||
/* XXX: For secure boot, we need our own loader here */ | dev->next = devinfo; | ||||
status = systab->BootServices->LoadImage(TRUE, image, bootdevpath, | |||||
buffer, bufsize, &loaderhandle); | |||||
if (EFI_ERROR(status)) | |||||
printf("LoadImage failed with error %lu\n", | |||||
status & ~EFI_ERROR_MASK); | |||||
status = systab->BootServices->HandleProtocol(loaderhandle, | |||||
&LoadedImageGUID, (VOID**)&loaded_image); | |||||
if (EFI_ERROR(status)) | |||||
printf("HandleProtocol failed with error %lu\n", | |||||
status & ~EFI_ERROR_MASK); | |||||
loaded_image->DeviceHandle = bootdevhandle; | |||||
status = systab->BootServices->StartImage(loaderhandle, NULL, NULL); | |||||
if (EFI_ERROR(status)) | |||||
printf("StartImage failed with error %lu\n", | |||||
status & ~EFI_ERROR_MASK); | |||||
} | } | ||||
static void | void | ||||
panic(const char *fmt, ...) | panic(const char *fmt, ...) | ||||
{ | { | ||||
char buf[128]; | char buf[128]; | ||||
va_list ap; | va_list ap; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
vsnprintf(buf, sizeof buf, fmt, ap); | vsnprintf(buf, sizeof buf, fmt, ap); | ||||
printf("panic: %s\n", buf); | printf("panic: %s\n", buf); | ||||
va_end(ap); | va_end(ap); | ||||
while (1) {} | while (1) {} | ||||
} | } | ||||
static int | int | ||||
printf(const char *fmt, ...) | printf(const char *fmt, ...) | ||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
int ret; | int ret; | ||||
/* Don't annoy the user as we probe for partitions */ | /* Don't annoy the user as we probe for partitions */ | ||||
if (strcmp(fmt,"Not ufs\n") == 0) | if (strcmp(fmt,"Not ufs\n") == 0) | ||||
return 0; | return 0; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
ret = vprintf(fmt, ap); | ret = __printf(fmt, putchr, 0, ap); | ||||
va_end(ap); | va_end(ap); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | void vprintf(const char *fmt, va_list ap) | ||||
putchar(char c, void *arg) | |||||
{ | { | ||||
CHAR16 buf[2]; | __printf(fmt, putchr, 0, ap); | ||||
if (c == '\n') { | |||||
buf[0] = '\r'; | |||||
buf[1] = 0; | |||||
systab->ConOut->OutputString(systab->ConOut, buf); | |||||
} | } | ||||
buf[0] = c; | |||||
buf[1] = 0; | |||||
systab->ConOut->OutputString(systab->ConOut, buf); | |||||
return (1); | |||||
} | |||||
static int | int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) | ||||
vprintf(const char *fmt, va_list ap) | |||||
{ | { | ||||
int ret; | |||||
ret = __printf(fmt, putchar, 0, ap); | |||||
return (ret); | |||||
} | |||||
static int | |||||
vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) | |||||
{ | |||||
struct sp_data sp; | struct sp_data sp; | ||||
int ret; | int ret; | ||||
sp.sp_buf = str; | sp.sp_buf = str; | ||||
sp.sp_len = 0; | sp.sp_len = 0; | ||||
sp.sp_size = sz; | sp.sp_size = sz; | ||||
ret = __printf(fmt, __sputc, &sp, ap); | ret = __printf(fmt, __sputc, &sp, ap); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) | __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) | ||||
{ | { | ||||
char buf[(sizeof(long) * 8) + 1]; | char buf[(sizeof(long) * 8) + 1]; | ||||
char *nbuf; | char *nbuf, *s; | ||||
u_long ul; | u_long ul; | ||||
u_int ui; | u_int ui; | ||||
int lflag; | int lflag, sflag, pad, ret, c; | ||||
int sflag; | |||||
char *s; | |||||
int pad; | |||||
int ret; | |||||
int c; | |||||
nbuf = &buf[sizeof buf - 1]; | nbuf = &buf[sizeof buf - 1]; | ||||
ret = 0; | ret = 0; | ||||
while ((c = *fmt++) != 0) { | while ((c = *fmt++) != 0) { | ||||
if (c != '%') { | if (c != '%') { | ||||
ret += putc(c, arg); | ret += putc(c, arg); | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 138 Lines • Show Last 20 Lines |
s/reverved/reserved/