// // get device path size // UINTN DevPathGetSize(EFI_DEVICE_PATH_PROTOCOL* devicePath) { if(!devicePath) return 0; EFI_DEVICE_PATH_PROTOCOL* start = devicePath; while(!EfiIsDevicePathEnd(devicePath)) devicePath = EfiNextDevicePathNode(devicePath); return ArchConvertPointerToAddress(devicePath) - ArchConvertPointerToAddress(start) + sizeof (EFI_DEVICE_PATH_PROTOCOL); }
EFI_RUNTIME_SERVICES* runtimeServicesInThunk = static_cast<EFI_RUNTIME_SERVICES*>(ArchpThunkCodeStart); UINT32 efiTableSize = sizeof(EFI_SYSTEM_TABLE64) + sizeof(EFI_RUNTIME_SERVICES64); efiTableSize = (efiTableSize + systemTable32->NumberOfTableEntries * sizeof(EFI_CONFIGURATION_TABLE64) + 15) & ~15; UINT64* efiMapL4 = Add2Ptr(ArchpThunkDataStart, ArchpThunkDataSize - EFI_PAGE_SIZE, UINT64*); EFI_SYSTEM_TABLE64* systemTable64 = Add2Ptr(efiMapL4, -static_cast<INTN>(efiTableSize), EFI_SYSTEM_TABLE64*); EFI_RUNTIME_SERVICES64* runtimeServices64 = Add2Ptr(systemTable64, sizeof(EFI_SYSTEM_TABLE64), EFI_RUNTIME_SERVICES64*); EFI_CONFIGURATION_TABLE64* configurationTable64 = Add2Ptr(runtimeServices64, sizeof(EFI_RUNTIME_SERVICES64), EFI_CONFIGURATION_TABLE64*); // // setup system table64 // systemTable64->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE; systemTable64->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION; systemTable64->Hdr.Reserved = 0; systemTable64->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE64); systemTable64->FirmwareVendor = ArchConvertPointerToAddress(systemTable32->FirmwareVendor) + thunkOffset; systemTable64->FirmwareRevision = systemTable32->FirmwareRevision; systemTable64->Padding = 0; systemTable64->ConsoleInHandle = 0; systemTable64->ConIn = 0; systemTable64->ConsoleOutHandle = 0; systemTable64->ConOut = 0; systemTable64->StandardErrorHandle = 0; systemTable64->StdErr = 0; systemTable64->RuntimeServices = ArchConvertPointerToAddress(runtimeServices64) + thunkOffset; systemTable64->BootServices = 0; systemTable64->NumberOfTableEntries = systemTable32->NumberOfTableEntries; systemTable64->ConfigurationTable = ArchConvertPointerToAddress(configurationTable64) + thunkOffset; // // setup configuration tables
// // append file path // EFI_DEVICE_PATH_PROTOCOL* DevPathAppendLastComponent(EFI_DEVICE_PATH_PROTOCOL* devicePath, CHAR8 CONST* fileName, BOOLEAN replaceLastComponent) { UINTN fileNameLength = strlen(fileName); UINTN length = DevPathGetSize(devicePath) + (fileNameLength + 1) * sizeof(CHAR16); EFI_DEVICE_PATH_PROTOCOL* newDevicePath = static_cast<EFI_DEVICE_PATH_PROTOCOL*>(MmAllocatePool(length)); if(!newDevicePath) return nullptr; EFI_DEVICE_PATH_PROTOCOL* dstDevicePath = newDevicePath; EFI_DEVICE_PATH_PROTOCOL* srcDevicePath = devicePath; FILEPATH_DEVICE_PATH* srcFilePath = nullptr; FILEPATH_DEVICE_PATH* dstFilePath = nullptr; while(!EfiIsDevicePathEnd(srcDevicePath)) { if(EfiDevicePathType(srcDevicePath) == MEDIA_DEVICE_PATH && srcDevicePath->SubType == MEDIA_FILEPATH_DP) { srcFilePath = _CR(srcDevicePath, FILEPATH_DEVICE_PATH, Header); dstFilePath = _CR(dstDevicePath, FILEPATH_DEVICE_PATH, Header); } memcpy(dstDevicePath, srcDevicePath, DevicePathNodeLength(srcDevicePath)); srcDevicePath = EfiNextDevicePathNode(srcDevicePath); dstDevicePath = EfiNextDevicePathNode(dstDevicePath); } if(!srcFilePath || !dstFilePath) { MmFreePool(newDevicePath); return nullptr; } dstFilePath->Header.Type = MEDIA_DEVICE_PATH; dstFilePath->Header.SubType = MEDIA_FILEPATH_DP; UINTN writePosition = 0; if(replaceLastComponent) { CHAR16* pathName = srcFilePath->PathName; CHAR16* lastDirectory = nullptr; UINTN pathLength = (DevicePathNodeLength(&srcFilePath->Header) - SIZE_OF_FILEPATH_DEVICE_PATH) / sizeof(CHAR16); for(UINTN i = 0; i < pathLength && pathName[i]; i ++) { if(pathName[i] == L'\\' || pathName[i] == L'/') lastDirectory = pathName + i; } if(lastDirectory) lastDirectory += 1; else lastDirectory = pathName; writePosition = lastDirectory - pathName; } else { writePosition = (DevicePathNodeLength(&srcFilePath->Header) - SIZE_OF_FILEPATH_DEVICE_PATH) / sizeof(CHAR16); while(!srcFilePath->PathName[writePosition - 1] && writePosition) writePosition -= 1; } UINTN usedLength = ArchConvertPointerToAddress(dstFilePath->PathName + writePosition) - ArchConvertPointerToAddress(newDevicePath); BlUtf8ToUnicode(fileName, fileNameLength, dstFilePath->PathName + writePosition, (length - usedLength - END_DEVICE_PATH_LENGTH) / sizeof(CHAR16)); UINTN nodeLength = SIZE_OF_FILEPATH_DEVICE_PATH + (wcslen(dstFilePath->PathName) + 1) * sizeof(CHAR16); SetDevicePathNodeLength(&dstFilePath->Header, nodeLength); EFI_DEVICE_PATH_PROTOCOL* endOfPath = NextDevicePathNode(&dstFilePath->Header); SetDevicePathEndNode(endOfPath); return newDevicePath; }