Creating a HTTP EFI handle
This commit is contained in:
parent
3fd0ea1b79
commit
c1f7148f30
2 changed files with 28 additions and 222 deletions
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
/* vim: et:sw=4:ts=4
|
||||
*
|
||||
* x86_64-efi/bootboot.c
|
||||
*
|
||||
* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
|
||||
|
|
@ -1453,17 +1454,11 @@ EFI_STATUS
|
|||
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
||||
{
|
||||
EFI_LOADED_IMAGE *loaded_image = NULL;
|
||||
EFI_GUID lipGuid = LOADED_IMAGE_PROTOCOL;
|
||||
EFI_GUID RomTableGuid = EFI_PCI_OPTION_ROM_TABLE_GUID;
|
||||
EFI_PCI_OPTION_ROM_TABLE *RomTable;
|
||||
EFI_GUID bioGuid = BLOCK_IO_PROTOCOL;
|
||||
EFI_BLOCK_IO *bio;
|
||||
EFI_HANDLE *handles = NULL;
|
||||
EFI_STATUS status=EFI_SUCCESS;
|
||||
EFI_MEMORY_DESCRIPTOR *memory_map = NULL, *mement;
|
||||
EFI_PARTITION_TABLE_HEADER *gptHdr;
|
||||
EFI_PARTITION_ENTRY *gptEnt;
|
||||
EFI_INPUT_KEY key;
|
||||
EFI_GUID http_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
|
||||
EFI_SERVICE_BINDING *http_binding;
|
||||
EFI_HANDLE http_handle;
|
||||
#if USE_MP_SERVICES
|
||||
EFI_EVENT Event;
|
||||
EFI_GUID mpspGuid = EFI_MP_SERVICES_PROTOCOL_GUID;
|
||||
|
|
@ -1474,16 +1469,14 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
|||
UINT64 ncycles = 0, currtime, endtime;
|
||||
UINTN bad_madt=0;
|
||||
#endif
|
||||
EFI_GUID SerIoGuid = EFI_SERIAL_IO_PROTOCOL_GUID;
|
||||
EFI_SERIAL_IO_PROTOCOL *ser = NULL;
|
||||
UINTN bsp_num=0, i, j=0, x,y, handle_size=0,memory_map_size=0, map_key=0, desc_size=0;
|
||||
UINTN bsp_num=0, i, j=0, x,y, memory_map_size=0, map_key=0, desc_size=0;
|
||||
UINT32 desc_version=0, a, b;
|
||||
UINT64 lba_s=0,lba_e=0,sysptr;
|
||||
MMapEnt *mmapent, *last=NULL, *sort;
|
||||
file_t ret={NULL,0};
|
||||
CHAR16 **argv, *initrdfile, *configfile, *help=
|
||||
CHAR16 **argv, *configfile, *help=
|
||||
L"SYNOPSIS\n BOOTBOOT.EFI [ -h | -? | /h | /? | -s ] [ INITRDFILE [ ENVIRONFILE [...] ] ]\n\nDESCRIPTION\n Bootstraps an operating system via the BOOTBOOT Protocol.\n If arguments not given, defaults to\n FS0:\\BOOTBOOT\\INITRD as ramdisk image and\n FS0:\\BOOTBOOT\\CONFIG for boot environment.\n Additional \"key=value\" command line arguments will be appended to the\n environment. If INITRD not found, it will use the first bootable partition\n in GPT. If CONFIG not found, it will look for /sys/config inside the\n INITRD (or partition). With -s it will scan the memory for an initrd ROM.\n\n As this is a loader, it is not supposed to return control to the shell.\n\n";
|
||||
INTN argc, scanmemory=0;
|
||||
INTN argc;
|
||||
|
||||
// Initialize UEFI Library
|
||||
InitializeLib(image, systab);
|
||||
|
|
@ -1498,16 +1491,8 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
|||
Print(L"BOOTBOOT LOADER (build %s)\n\n%s",a2u(__DATE__),help);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
if(argv[1][0]=='-'||argv[1][0]=='s') {
|
||||
argc--; argv++; scanmemory = 1;
|
||||
}
|
||||
}
|
||||
if(argc>1) {
|
||||
initrdfile=argv[1];
|
||||
} else {
|
||||
initrdfile=L"\\BOOTBOOT\\INITRD";
|
||||
}
|
||||
if(argc>2) {
|
||||
configfile=argv[2];
|
||||
} else {
|
||||
configfile=L"\\BOOTBOOT\\CONFIG";
|
||||
|
|
@ -1562,205 +1547,28 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
|
|||
} while(0)
|
||||
#endif
|
||||
|
||||
// locate InitRD in ROM
|
||||
DBG(L" * Locate initrd in Option ROMs%s\n",L"");
|
||||
RomTable = NULL; initrd.ptr = NULL; initrd.size = 0;
|
||||
status=EFI_LOAD_ERROR;
|
||||
// first, try RomTable
|
||||
LibGetSystemConfigurationTable(&RomTableGuid,(void *)&(RomTable));
|
||||
if(RomTable!=NULL) {
|
||||
for (i=0;i<RomTable->PciOptionRomCount;i++) {
|
||||
ret.ptr=(UINT8*)RomTable->PciOptionRomDescriptors[i].RomAddress;
|
||||
if(ret.ptr[0]==0x55 && ret.ptr[1]==0xAA && !CompareMem(ret.ptr+8,(const CHAR8 *)"INITRD",6)) {
|
||||
CopyMem(&initrd.size,ret.ptr+16,4);
|
||||
initrd.ptr=ret.ptr+32;
|
||||
status=EFI_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if not found, scan memory
|
||||
if(scanmemory && (EFI_ERROR(status) || initrd.ptr==NULL)){
|
||||
status = uefi_call_wrapper(BS->GetMemoryMap, 5,
|
||||
&memory_map_size, memory_map, NULL, &desc_size, NULL);
|
||||
if (status!=EFI_BUFFER_TOO_SMALL || memory_map_size==0) {
|
||||
return report(EFI_OUT_OF_RESOURCES,L"GetMemoryMap getSize");
|
||||
}
|
||||
memory_map_size+=2*desc_size;
|
||||
memory_map = NULL;
|
||||
status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2,
|
||||
(memory_map_size+PAGESIZE-1)/PAGESIZE,
|
||||
(EFI_PHYSICAL_ADDRESS*)&memory_map);
|
||||
if (EFI_ERROR(status) || memory_map == NULL) {
|
||||
return report(EFI_OUT_OF_RESOURCES,L"AllocatePages");
|
||||
}
|
||||
status = uefi_call_wrapper(BS->GetMemoryMap, 5,
|
||||
&memory_map_size, memory_map, &map_key, &desc_size, &desc_version);
|
||||
status=EFI_LOAD_ERROR;
|
||||
for(mement=memory_map;
|
||||
mement<memory_map+memory_map_size;
|
||||
mement=NextMemoryDescriptor(mement,desc_size)) {
|
||||
if(mement==NULL || (mement->PhysicalStart==0 && mement->NumberOfPages==0))
|
||||
break;
|
||||
// skip free and ACPI memory
|
||||
if(mement->Type==7||(mement->Type>=9&&mement->Type<=13))
|
||||
continue;
|
||||
// according to spec, EFI Option ROMs must start on 512 bytes boundary, not 2048
|
||||
for(ret.ptr=(UINT8*)mement->PhysicalStart;
|
||||
ret.ptr+512<(UINT8*)mement->PhysicalStart+mement->NumberOfPages*PAGESIZE;
|
||||
ret.ptr+=512) {
|
||||
if(ret.ptr[0]==0x55 && ret.ptr[1]==0xAA && !CompareMem(ret.ptr+8,(const CHAR8 *)"INITRD",6)) {
|
||||
CopyMem(&initrd.size,ret.ptr+16,4);
|
||||
initrd.ptr=ret.ptr+32;
|
||||
status=EFI_SUCCESS;
|
||||
goto foundinrom;
|
||||
}
|
||||
}
|
||||
}
|
||||
foundinrom:
|
||||
uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)memory_map, (memory_map_size+PAGESIZE-1)/PAGESIZE);
|
||||
}
|
||||
// try reading the initrd from serial line
|
||||
if(EFI_ERROR(status) || initrd.ptr==NULL){
|
||||
status = uefi_call_wrapper(BS->LocateProtocol, 3, &SerIoGuid, NULL, (void**)&ser);
|
||||
if(!EFI_ERROR(status) && ser) {
|
||||
// 1000 microsec timeout, mode 115200,8,n,1
|
||||
status = uefi_call_wrapper(ser->SetAttributes, 7, ser, 115200, 0, 1000, NoParity, 8, OneStopBit);
|
||||
if(!EFI_ERROR(status)) {
|
||||
i = 3;
|
||||
uefi_call_wrapper(ser->Write, 3, ser, &i, "\003\003\003");
|
||||
i = 4; initrd.size = 0;
|
||||
status = uefi_call_wrapper(ser->Read, 3, ser, &i, (VOID*)&initrd.size);
|
||||
if(!EFI_ERROR(status) && i == 4) {
|
||||
i = 2;
|
||||
if(initrd.size < 32 || initrd.size >= INITRD_MAXSIZE*1024*1024) {
|
||||
uefi_call_wrapper(ser->Write, 3, ser, &i, "SE");
|
||||
initrd.size = 0;
|
||||
status = EFI_LOAD_ERROR;
|
||||
} else {
|
||||
initrd.ptr = NULL;
|
||||
status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, (initrd.size+PAGESIZE-1)/PAGESIZE,
|
||||
(EFI_PHYSICAL_ADDRESS*)&initrd.ptr);
|
||||
if (EFI_ERROR(status) || initrd.ptr == NULL) {
|
||||
uefi_call_wrapper(ser->Write, 3, ser, &i, "SE");
|
||||
return report(EFI_OUT_OF_RESOURCES,L"AllocatePages");
|
||||
}
|
||||
uefi_call_wrapper(ser->Write, 3, ser, &i, "OK");
|
||||
i = initrd.size;
|
||||
status = uefi_call_wrapper(ser->Read, 3, ser, &i, (VOID*)initrd.ptr);
|
||||
if(EFI_ERROR(status) || i != initrd.size) {
|
||||
uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)initrd.ptr,
|
||||
(initrd.size+PAGESIZE-1)/PAGESIZE);
|
||||
initrd.ptr = NULL;
|
||||
initrd.size = 0;
|
||||
status = EFI_LOAD_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fall back to INITRD on filesystem
|
||||
if(EFI_ERROR(status) || initrd.ptr==NULL){
|
||||
// if the user presses any key now, we fallback to backup initrd
|
||||
for(i=0;i<500;i++) {
|
||||
if(!uefi_call_wrapper(BS->CheckEvent, 1, CI->WaitForKey)) {
|
||||
uefi_call_wrapper(CI->ReadKeyStroke, 2, CI, &key);
|
||||
Print(L" * Backup initrd\n");
|
||||
initrdfile=L"\\BOOTBOOT\\INITRD.BAK";
|
||||
break;
|
||||
}
|
||||
// delay 1ms
|
||||
uefi_call_wrapper(BS->Stall, 1, 1000);
|
||||
}
|
||||
DBG(L" * Locate initrd in %s\n",initrdfile);
|
||||
// Initialize FS with the DeviceHandler from loaded image protocol
|
||||
status = uefi_call_wrapper(BS->HandleProtocol,
|
||||
3,
|
||||
image,
|
||||
&lipGuid,
|
||||
(void **) &loaded_image);
|
||||
if (!EFI_ERROR(status) && loaded_image!=NULL) {
|
||||
status=EFI_LOAD_ERROR;
|
||||
RootDir = LibOpenRoot(loaded_image->DeviceHandle);
|
||||
// load ramdisk
|
||||
status=LoadFile(initrdfile,&initrd.ptr, &initrd.size);
|
||||
}
|
||||
}
|
||||
// if not found, try architecture specific initrd file
|
||||
if(EFI_ERROR(status) || initrd.ptr==NULL){
|
||||
initrdfile=L"\\BOOTBOOT\\X86_64";
|
||||
DBG(L" * Locate initrd in %s\n",initrdfile);
|
||||
status=LoadFile(initrdfile,&initrd.ptr, &initrd.size);
|
||||
}
|
||||
// if even that failed, look for a partition
|
||||
if(status!=EFI_SUCCESS || initrd.size==0){
|
||||
DBG(L" * Locate initrd in GPT%s\n",L"");
|
||||
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &bioGuid, NULL, &handle_size, handles);
|
||||
if (status!=EFI_BUFFER_TOO_SMALL || handle_size==0) {
|
||||
return report(EFI_OUT_OF_RESOURCES,L"LocateHandle getSize");
|
||||
}
|
||||
handles = NULL;
|
||||
status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, (handle_size+PAGESIZE-1)/PAGESIZE,
|
||||
(EFI_PHYSICAL_ADDRESS*)&handles);
|
||||
if(EFI_ERROR(status) || handles == NULL)
|
||||
return report(EFI_OUT_OF_RESOURCES,L"AllocatePages\n");
|
||||
initrd.ptr = NULL;
|
||||
status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, 1, (EFI_PHYSICAL_ADDRESS*)&initrd.ptr);
|
||||
if (EFI_ERROR(status) || initrd.ptr == NULL)
|
||||
return report(EFI_OUT_OF_RESOURCES,L"AllocatePages");
|
||||
lba_s=lba_e=0;
|
||||
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &bioGuid, NULL, &handle_size, handles);
|
||||
for(i=0;i<handle_size/sizeof(EFI_HANDLE);i++) {
|
||||
// we have to do it the hard way. HARDDRIVE_DEVICE_PATH does not return partition type or attribs...
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &bioGuid, (void **) &bio);
|
||||
if(status!=EFI_SUCCESS || bio==NULL || bio->Media->BlockSize==0)
|
||||
continue;
|
||||
status = uefi_call_wrapper(bio->ReadBlocks, 5, bio, bio->Media->MediaId, 1, PAGESIZE, initrd.ptr);
|
||||
if(status!=EFI_SUCCESS || CompareMem(initrd.ptr,EFI_PTAB_HEADER_ID,8))
|
||||
continue;
|
||||
gptHdr = (EFI_PARTITION_TABLE_HEADER*)initrd.ptr;
|
||||
if(gptHdr->NumberOfPartitionEntries>127) gptHdr->NumberOfPartitionEntries=127;
|
||||
// first, look for a partition with bootable flag
|
||||
ret.ptr= (UINT8*)(initrd.ptr + (gptHdr->PartitionEntryLBA-1) * bio->Media->BlockSize);
|
||||
for(j=0;j<gptHdr->NumberOfPartitionEntries;j++) {
|
||||
gptEnt=(EFI_PARTITION_ENTRY*)ret.ptr;
|
||||
if((ret.ptr[0]==0 && ret.ptr[1]==0 && ret.ptr[2]==0 && ret.ptr[3]==0) || gptEnt->StartingLBA==0)
|
||||
break;
|
||||
// use first partition with bootable flag as INITRD
|
||||
if((gptEnt->Attributes & EFI_PART_USED_BY_OS)) goto partfound;
|
||||
ret.ptr+=gptHdr->SizeOfPartitionEntry;
|
||||
}
|
||||
// if none, look for specific partition types
|
||||
ret.ptr= (UINT8*)(initrd.ptr + (gptHdr->PartitionEntryLBA-1) * bio->Media->BlockSize);
|
||||
for(j=0;j<gptHdr->NumberOfPartitionEntries;j++) {
|
||||
gptEnt=(EFI_PARTITION_ENTRY*)ret.ptr;
|
||||
if((ret.ptr[0]==0 && ret.ptr[1]==0 && ret.ptr[2]==0 && ret.ptr[3]==0) || gptEnt->StartingLBA==0)
|
||||
break;
|
||||
// use the first OS/Z root partition for this architecture
|
||||
if(!CompareMem(&gptEnt->PartitionTypeGUID.Data1,"OS/Z",4) &&
|
||||
gptEnt->PartitionTypeGUID.Data2==0x8664 &&
|
||||
!CompareMem(&gptEnt->PartitionTypeGUID.Data4[4],"root",4)) {
|
||||
partfound: lba_s=gptEnt->StartingLBA; lba_e=gptEnt->EndingLBA;
|
||||
initrd.size = (((lba_e-lba_s)*bio->Media->BlockSize + PAGESIZE-1)/PAGESIZE)*PAGESIZE;
|
||||
status=EFI_SUCCESS;
|
||||
goto partok;
|
||||
}
|
||||
ret.ptr+=gptHdr->SizeOfPartitionEntry;
|
||||
}
|
||||
}
|
||||
return report(EFI_LOAD_ERROR,L"No boot partition");
|
||||
partok:
|
||||
uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)initrd.ptr, 1);
|
||||
if(initrd.size>0 && bio!=NULL) {
|
||||
initrd.ptr = NULL;
|
||||
status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, initrd.size/PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&initrd.ptr);
|
||||
if (EFI_ERROR(status) || initrd.ptr == NULL)
|
||||
return report(EFI_OUT_OF_RESOURCES,L"AllocatePages");
|
||||
status = uefi_call_wrapper(bio->ReadBlocks, 5, bio, bio->Media->MediaId, lba_s, initrd.size, initrd.ptr);
|
||||
} else
|
||||
// Try to locate HTTP service binding protocol
|
||||
DBG(L" * Locating HTTP service binding protocol%s\n", L"");
|
||||
status = uefi_call_wrapper(BS->LocateProtocol, 3, &http_binding_guid, NULL, (void **)&http_binding);
|
||||
if (EFI_ERROR(status)) {
|
||||
return report(status, L"LocateProtocol");
|
||||
}
|
||||
|
||||
// Create a HTTP protocol handle
|
||||
DBG(L" * Creating HTTP protocol handle%s\n", L"");
|
||||
http_handle=NULL;
|
||||
status = uefi_call_wrapper(http_binding->CreateChild, 2, http_binding, &http_handle);
|
||||
if (EFI_ERROR(status)) {
|
||||
return report(status, L"CreateChild");
|
||||
}
|
||||
|
||||
status=EFI_LOAD_ERROR;
|
||||
|
||||
// Retrieve InitRD from external HTTP server
|
||||
{
|
||||
for (;;) {}
|
||||
}
|
||||
|
||||
if(status==EFI_SUCCESS && initrd.size>0){
|
||||
//check if initrd is gzipped
|
||||
if(initrd.ptr[0]==0x1f && initrd.ptr[1]==0x8b){
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@
|
|||
{0x7A59B29B, 0x910B, 0x4171,\
|
||||
{0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B}}
|
||||
|
||||
INTERFACE_DECL(_EFI_HTTP);
|
||||
|
||||
typedef struct _EFI_HTTP_PROTOCOL EFI_HTTP_PROTOCOL;
|
||||
|
||||
//*******************************************
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue