Changeset View
Changeset View
Standalone View
Standalone View
sys/boot/efi/boot1/boot1.c
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*)) | #define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*)) | ||||
/* The initial number of handles used to query EFI for partitions. */ | /* The initial number of handles used to query EFI for partitions. */ | ||||
#define NUM_HANDLES_INIT 24 | #define NUM_HANDLES_INIT 24 | ||||
void putchar(int c); | void putchar(int c); | ||||
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); | EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); | ||||
static void try_load(const boot_module_t* mod); | static void try_load(const boot_module_t* mod); | ||||
static EFI_STATUS probe_handle(EFI_HANDLE h); | static void probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, | ||||
BOOLEAN match); | |||||
static EFI_STATUS probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, | |||||
BOOLEAN match); | |||||
EFI_SYSTEM_TABLE *systab; | EFI_SYSTEM_TABLE *systab; | ||||
EFI_BOOT_SERVICES *bs; | EFI_BOOT_SERVICES *bs; | ||||
static EFI_HANDLE *image; | static EFI_HANDLE *image; | ||||
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; | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | printf("Failed to start image provided by %s (%lu)\n", | ||||
mod->name, EFI_ERROR_CODE(status)); | mod->name, EFI_ERROR_CODE(status)); | ||||
free(cmd); | free(cmd); | ||||
loaded_image->LoadOptionsSize = 0; | loaded_image->LoadOptionsSize = 0; | ||||
loaded_image->LoadOptions = NULL; | loaded_image->LoadOptions = NULL; | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
static BOOLEAN | |||||
paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) | |||||
{ | |||||
int len; | |||||
if (imgpath == NULL || imgpath->Type != devpath->Type || | |||||
imgpath->SubType != devpath->SubType) | |||||
return (FALSE); | |||||
len = DevicePathNodeLength(imgpath); | |||||
if (len != DevicePathNodeLength(devpath)) | |||||
return (FALSE); | |||||
return (memcmp(imgpath, devpath, (size_t)len) == 0); | |||||
} | |||||
static EFI_DEVICE_PATH * | |||||
messaging_path(EFI_DEVICE_PATH *devpath) | |||||
{ | |||||
while (!IsDevicePathMessaging(devpath) && | |||||
!IsDevicePathEnd(NextDevicePathNode(devpath))) | |||||
devpath = NextDevicePathNode(devpath); | |||||
if (!IsDevicePathMessaging(devpath)) | |||||
return (NULL); | |||||
return (devpath); | |||||
} | |||||
EFI_STATUS | EFI_STATUS | ||||
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) | efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) | ||||
{ | { | ||||
EFI_HANDLE *handles; | EFI_HANDLE *handles; | ||||
EFI_LOADED_IMAGE *img; | |||||
EFI_DEVICE_PATH *imgpath; | |||||
EFI_STATUS status; | EFI_STATUS status; | ||||
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; | EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; | ||||
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; | SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; | ||||
UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; | UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; | ||||
/* Basic initialization*/ | /* Basic initialization*/ | ||||
systab = Xsystab; | systab = Xsystab; | ||||
image = Ximage; | image = Ximage; | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) | ||||
default: | default: | ||||
panic("Failed to get device handles (%lu)", | panic("Failed to get device handles (%lu)", | ||||
EFI_ERROR_CODE(status)); | EFI_ERROR_CODE(status)); | ||||
} | } | ||||
/* Scan all partitions, probing with all modules. */ | /* Scan all partitions, probing with all modules. */ | ||||
nhandles = hsize / sizeof(*handles); | nhandles = hsize / sizeof(*handles); | ||||
printf(" Probing %zu block devices...", nhandles); | printf(" Probing %zu block devices...", nhandles); | ||||
for (i = 0; i < nhandles; i++) { | |||||
status = probe_handle(handles[i]); | /* | ||||
switch (status) { | * We start by probing handles which match our images media path, so if | ||||
case EFI_UNSUPPORTED: | * possible we boot from a partition on our device. | ||||
printf("."); | */ | ||||
break; | status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img); | ||||
case EFI_SUCCESS: | imgpath = NULL; | ||||
printf("+"); | if (status == EFI_SUCCESS) { | ||||
break; | status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID, | ||||
default: | (void **)&imgpath); | ||||
printf("x"); | if (status == EFI_SUCCESS) { | ||||
break; | imgpath = messaging_path(imgpath); | ||||
if (imgpath != NULL) { | |||||
for (i = 0; i < nhandles; i++) | |||||
probe_handle_status(handles[i], imgpath, | |||||
TRUE); | |||||
} | } | ||||
} | } | ||||
} | |||||
/* Now check for other bootable partitions. */ | |||||
for (i = 0; i < nhandles; i++) | |||||
probe_handle_status(handles[i], imgpath, FALSE); | |||||
printf(" done\n"); | printf(" done\n"); | ||||
/* Status summary. */ | /* Status summary. */ | ||||
for (i = 0; i < NUM_BOOT_MODULES; i++) { | for (i = 0; i < NUM_BOOT_MODULES; i++) { | ||||
if (boot_modules[i] != NULL) { | if (boot_modules[i] != NULL) { | ||||
printf(" "); | printf(" "); | ||||
boot_modules[i]->status(); | boot_modules[i]->status(); | ||||
} | } | ||||
} | } | ||||
/* Select a partition to boot by trying each module in order. */ | /* Select a partition to boot by trying each module in order. */ | ||||
for (i = 0; i < NUM_BOOT_MODULES; i++) | for (i = 0; i < NUM_BOOT_MODULES; i++) | ||||
if (boot_modules[i] != NULL) | if (boot_modules[i] != NULL) | ||||
try_load(boot_modules[i]); | try_load(boot_modules[i]); | ||||
/* If we get here, we're out of luck... */ | /* If we get here, we're out of luck... */ | ||||
panic("No bootable partitions found!"); | panic("No bootable partitions found!"); | ||||
} | } | ||||
static void | |||||
probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN match) | |||||
{ | |||||
switch (probe_handle(h, imgpath, match)) { | |||||
case EFI_UNSUPPORTED: | |||||
printf("."); | |||||
break; | |||||
case EFI_SUCCESS: | |||||
printf("%c", match ? '*' : '+'); | |||||
break; | |||||
case EFI_NOT_FOUND: | |||||
/* Didn't match or already tested. */ | |||||
break; | |||||
default: | |||||
printf("x"); | |||||
break; | |||||
} | |||||
} | |||||
static EFI_STATUS | static EFI_STATUS | ||||
probe_handle(EFI_HANDLE h) | probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN match) | ||||
{ | { | ||||
dev_info_t *devinfo; | dev_info_t *devinfo; | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
EFI_DEVICE_PATH *devpath; | EFI_DEVICE_PATH *devpath; | ||||
EFI_STATUS status; | EFI_STATUS status; | ||||
BOOLEAN matched; | |||||
UINTN i; | UINTN i; | ||||
/* Figure out if we're dealing with an actual partition. */ | /* Figure out if we're dealing with an actual partition. */ | ||||
status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); | status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); | ||||
if (status == EFI_UNSUPPORTED) | if (status == EFI_UNSUPPORTED) | ||||
return (status); | return (status); | ||||
if (status != EFI_SUCCESS) { | if (status != EFI_SUCCESS) { | ||||
DPRINTF("\nFailed to query DevicePath (%lu)\n", | DPRINTF("\nFailed to query DevicePath (%lu)\n", | ||||
EFI_ERROR_CODE(status)); | EFI_ERROR_CODE(status)); | ||||
return (status); | return (status); | ||||
} | } | ||||
while (!IsDevicePathEnd(NextDevicePathNode(devpath))) | matched = FALSE; | ||||
while (!IsDevicePathEnd(NextDevicePathNode(devpath))) { | |||||
if (IsDevicePathMessaging(devpath) && !matched) { | |||||
if (match) { | |||||
if (!paths_match(imgpath, devpath)) | |||||
return (EFI_NOT_FOUND); | |||||
matched = TRUE; | |||||
} else if (paths_match(imgpath, devpath)) { | |||||
/* Already tested. */ | |||||
return (EFI_NOT_FOUND); | |||||
} | |||||
} | |||||
devpath = NextDevicePathNode(devpath); | devpath = NextDevicePathNode(devpath); | ||||
} | |||||
if (IsDevicePathMessaging(devpath)) { | |||||
if (match) { | |||||
if (!paths_match(imgpath, devpath)) | |||||
return (EFI_NOT_FOUND); | |||||
matched = TRUE; | |||||
} else if (paths_match(imgpath, devpath)) { | |||||
/* Already tested. */ | |||||
return (EFI_NOT_FOUND); | |||||
} | |||||
} | |||||
if (match && !matched) | |||||
return (EFI_NOT_FOUND); | |||||
status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); | status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); | ||||
if (status == EFI_UNSUPPORTED) | if (status == EFI_UNSUPPORTED) | ||||
return (status); | return (status); | ||||
if (status != EFI_SUCCESS) { | if (status != EFI_SUCCESS) { | ||||
DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", | DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", | ||||
EFI_ERROR_CODE(status)); | EFI_ERROR_CODE(status)); | ||||
▲ Show 20 Lines • Show All 77 Lines • Show Last 20 Lines |