Changeset View
Standalone View
sys/boot/efi/boot1/boot1.c
Context not available. | |||||
* 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 reverved. | |||||
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 | ||||
Context not available. | |||||
__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> | ||||
Context not available. | |||||
#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); | ||||
Context not available. | |||||
u_int sp_size; | u_int sp_size; | ||||
}; | }; | ||||
static const boot_module_t *boot_modules[] = | |||||
{ | |||||
#ifdef ZFS_EFI_BOOT | |||||
&zfs_module, | |||||
#endif | |||||
#ifdef UFS_EFI_BOOT | |||||
&ufs_module | |||||
#endif | |||||
}; | |||||
#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*)) | |||||
static const char digits[] = "0123456789abcdef"; | static const char digits[] = "0123456789abcdef"; | ||||
static void panic(const char *fmt, ...) __dead2; | |||||
static int printf(const char *fmt, ...); | |||||
static int putchar(char c, void *arg); | |||||
static int vprintf(const char *fmt, va_list ap); | |||||
static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); | |||||
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) | |||||
{ | |||||
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… | |||||
void *out; | |||||
Done Inline ActionsWhat's this capital-M Malloc used for? emaste: What's this capital-M Malloc used for? | |||||
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)… | |||||
if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS) | |||||
return (out); | |||||
return (NULL); | |||||
} | |||||
char * | |||||
strcpy(char *dst, const char *src) | |||||
{ | |||||
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. | |||||
int i; | |||||
Done Inline Actionscan we link against libstand for these? emaste: can we link against libstand for these? | |||||
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 | |||||
for (i = 0; src[i]; i++) | |||||
dst[i] = src[i]; | |||||
dst[i] = '\0'; | |||||
return (dst); | |||||
} | |||||
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 *a, const char *b, size_t len) | |||||
{ | |||||
int i; | |||||
for (i = 0; i < len; i++) { | |||||
if (a[i] == '\0' && b[i] == '\0') | |||||
return (0); | |||||
else if (a[i] < b[i]) | |||||
return (-1); | |||||
else if (a[i] > b[i]) | |||||
return (1); | |||||
} | |||||
return (0); | |||||
} | |||||
size_t | |||||
strlen(const char *s) | |||||
{ | |||||
size_t len = 0; | |||||
for (; *s != '\0'; s++, len++) | |||||
; | |||||
return (len); | |||||
} | |||||
char * | |||||
strdup(const char *s) | |||||
{ | |||||
char *out; | |||||
out = malloc(strlen(s) + 1); | |||||
if (out == NULL) | |||||
return (NULL); | |||||
strcpy(out, s); | |||||
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; | ||||
Context not available. | |||||
*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) | ||||
{ | { | ||||
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) | ||||
{ | { | ||||
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') { | |||||
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 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, | |||||
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, | |||||
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, 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, | |||||
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, | ||||
Context not available. | |||||
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) { | ||||
Context not available. | |||||
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 = sizeof(EFI_HANDLE) * 24; | ||||
if (EFI_ERROR(status)) | if (bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles) != EFI_SUCCESS) | ||||
continue; | panic("Failed to allocate handles"); | ||||
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", status); | |||||
break; | |||||
default: | |||||
panic("Failed to get device handles (%lu)", 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) | /* Summary status. */ | ||||
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; | |||||
} | } | ||||
static int | static EFI_STATUS | ||||
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. | |||||
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", status); | ||||
return (status); | |||||
} | |||||
return (0); | while (!IsDevicePathEnd(NextDevicePathNode(devpath))) | ||||
} | devpath = NextDevicePathNode(devpath); | ||||
#include "ufsread.c" | status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); | ||||
if (status == EFI_UNSUPPORTED) | |||||
return (status); | |||||
static ssize_t | if (status != EFI_SUCCESS) { | ||||
fsstat(ufs_ino_t inode) | DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", status); | ||||
{ | 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; | |||||
indbuf = dmadat->indbuf; | |||||
if (!dsk_meta) { | |||||
inomap = 0; | |||||
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) | status); | ||||
printf("domount: can't read superblock\n"); | continue; | ||||
return (-1); | } | ||||
devinfo->dev = blkio; | |||||
devinfo->devpath = devpath; | |||||
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); | |||||
} | } | ||||
if (!quiet) | |||||
printf("Succesfully mounted UFS filesystem\n"); | return (EFI_UNSUPPORTED); | ||||
return (0); | |||||
} | } | ||||
static void | void | ||||
load(const char *fname) | add_device(dev_info_t **devinfop, dev_info_t *devinfo) | ||||
{ | { | ||||
ufs_ino_t ino; | dev_info_t *dev; | ||||
EFI_STATUS status; | |||||
EFI_HANDLE loaderhandle; | if (*devinfop == NULL) { | ||||
EFI_LOADED_IMAGE *loaded_image; | *devinfop = devinfo; | ||||
void *buffer; | |||||
size_t bufsize; | |||||
if ((ino = lookup(fname)) == 0) { | |||||
printf("File %s not found\n", fname); | |||||
return; | return; | ||||
} | } | ||||
Done Inline Actionstrailing whitespace emaste: trailing whitespace | |||||
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 %lx\n", status); | |||||
status = systab->BootServices->HandleProtocol(loaderhandle, | |||||
&LoadedImageGUID, (VOID**)&loaded_image); | |||||
if (EFI_ERROR(status)) | |||||
printf("HandleProtocol failed with error %lx\n", status); | |||||
loaded_image->DeviceHandle = bootdevhandle; | |||||
status = systab->BootServices->StartImage(loaderhandle, NULL, NULL); | |||||
if (EFI_ERROR(status)) | |||||
printf("StartImage failed with error %lx\n", status); | |||||
} | } | ||||
static void | void | ||||
panic(const char *fmt, ...) | panic(const char *fmt, ...) | ||||
{ | { | ||||
char buf[128]; | char buf[128]; | ||||
Context not available. | |||||
while (1) {} | while (1) {} | ||||
} | } | ||||
static int | int | ||||
printf(const char *fmt, ...) | printf(const char *fmt, ...) | ||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
Context not available. | |||||
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; | ||||
Context not available. | |||||
__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; | ||||
Context not available. |
s/reverved/reserved/