1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
// SPDX-License-Identifier: BSD-2-Clause-Patent
#include "shim.h"
EFI_STATUS
get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize)
{
EFI_STATUS efi_status;
void *buffer = NULL;
UINTN bs = 0;
/* The API here is "Call it once with bs=0, it fills in bs,
* then allocate a buffer and ask again to get it filled. */
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, NULL);
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL)
return efi_status;
if (bs == 0)
return EFI_SUCCESS;
buffer = AllocateZeroPool(bs);
if (!buffer) {
console_print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, buffer);
/* This checks *either* the error from the first GetInfo, if it isn't
* the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo
* call in *any* case. */
if (EFI_ERROR(efi_status)) {
console_print(L"Could not get file info: %r\n", efi_status);
if (buffer)
FreePool(buffer);
return efi_status;
}
EFI_FILE_INFO *fi = buffer;
*retsize = fi->FileSize;
FreePool(buffer);
return EFI_SUCCESS;
}
EFI_STATUS
read_file(EFI_FILE_HANDLE fh, CHAR16 *fullpath, CHAR16 **buffer, UINT64 *bs)
{
EFI_FILE_HANDLE fh2;
EFI_STATUS efi_status;
efi_status = fh->Open(fh, &fh2, fullpath, EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status)) {
console_print(L"Couldn't open \"%s\": %r\n", fullpath, efi_status);
return efi_status;
}
UINTN len = 0;
CHAR16 *b = NULL;
efi_status = get_file_size(fh2, &len);
if (EFI_ERROR(efi_status)) {
console_print(L"Could not get file size for \"%s\": %r\n",
fullpath, efi_status);
fh2->Close(fh2);
return efi_status;
}
if (len > 1024 * PAGE_SIZE) {
fh2->Close(fh2);
return EFI_BAD_BUFFER_SIZE;
}
b = AllocateZeroPool(len + 2);
if (!b) {
console_print(L"Could not allocate memory\n");
fh2->Close(fh2);
return EFI_OUT_OF_RESOURCES;
}
efi_status = fh->Read(fh, &len, b);
if (EFI_ERROR(efi_status)) {
FreePool(b);
fh2->Close(fh2);
console_print(L"Could not read file: %r\n", efi_status);
return efi_status;
}
*buffer = b;
*bs = len;
fh2->Close(fh2);
return EFI_SUCCESS;
}
|