| 4372 | } |
| 4373 | |
| 4374 | UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base, const QModelIndex & index) |
| 4375 | { |
| 4376 | UINT32 delta; // Difference between old and new base addresses |
| 4377 | UINT32 relocOffset; // Offset of relocation region |
| 4378 | UINT32 relocSize; // Size of relocation region |
| 4379 | UINT32 teFixup = 0; // Bytes removed form PE header for TE images |
| 4380 | |
| 4381 | // Copy input data to local storage |
| 4382 | QByteArray file = executable; |
| 4383 | |
| 4384 | // Populate DOS header |
| 4385 | if ((UINT32)file.size() < sizeof(EFI_IMAGE_DOS_HEADER)) |
| 4386 | return ERR_INVALID_FILE; |
| 4387 | EFI_IMAGE_DOS_HEADER* dosHeader = (EFI_IMAGE_DOS_HEADER*)file.data(); |
| 4388 | |
| 4389 | // Check signature |
| 4390 | if (dosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE){ |
| 4391 | UINT32 offset = dosHeader->e_lfanew; |
| 4392 | if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_PE_HEADER)) |
| 4393 | return ERR_UNKNOWN_IMAGE_TYPE; |
| 4394 | EFI_IMAGE_PE_HEADER* peHeader = (EFI_IMAGE_PE_HEADER*)(file.data() + offset); |
| 4395 | if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) |
| 4396 | return ERR_UNKNOWN_IMAGE_TYPE; |
| 4397 | offset += sizeof(EFI_IMAGE_PE_HEADER); |
| 4398 | // Skip file header |
| 4399 | offset += sizeof(EFI_IMAGE_FILE_HEADER); |
| 4400 | // Check optional header magic |
| 4401 | if ((UINT32)file.size() < offset + sizeof(UINT16)) |
| 4402 | return ERR_UNKNOWN_IMAGE_TYPE; |
| 4403 | UINT16 magic = *(UINT16*)(file.data() + offset); |
| 4404 | if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) { |
| 4405 | if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER32)) |
| 4406 | return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; |
| 4407 | EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (EFI_IMAGE_OPTIONAL_HEADER32*)(file.data() + offset); |
| 4408 | delta = base - optHeader->ImageBase; |
| 4409 | if (!delta) |
| 4410 | // No need to rebase |
| 4411 | return ERR_SUCCESS; |
| 4412 | relocOffset = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; |
| 4413 | relocSize = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; |
| 4414 | // Set new base |
| 4415 | optHeader->ImageBase = base; |
| 4416 | } |
| 4417 | else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { |
| 4418 | if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER64)) |
| 4419 | return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; |
| 4420 | EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (EFI_IMAGE_OPTIONAL_HEADER64*)(file.data() + offset); |
| 4421 | delta = base - optHeader->ImageBase; |
| 4422 | if (!delta) |
| 4423 | // No need to rebase |
| 4424 | return ERR_SUCCESS; |
| 4425 | relocOffset = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; |
| 4426 | relocSize = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; |
| 4427 | // Set new base |
| 4428 | optHeader->ImageBase = base; |
| 4429 | } |
| 4430 | else |
| 4431 | return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; |