diff options
Diffstat (limited to 'netboot.c')
| -rw-r--r-- | netboot.c | 68 |
1 files changed, 64 insertions, 4 deletions
@@ -16,6 +16,16 @@ #define ntohs(x) __builtin_bswap16(x) /* supported both by GCC and clang */ #define htons(x) ntohs(x) +/* TFTP error codes from RFC 1350 */ +#define TFTP_ERROR_NOT_DEFINED 0 /* Not defined, see error message (if any). */ +#define TFTP_ERROR_NOT_FOUND 1 /* File not found. */ +#define TFTP_ERROR_ACCESS 2 /* Access violation. */ +#define TFTP_ERROR_NO_SPACE 3 /* Disk full or allocation exceeded. */ +#define TFTP_ERROR_ILLEGAL_OP 4 /* Illegal TFTP operation. */ +#define TFTP_ERROR_UNKNOWN_ID 5 /* Unknown transfer ID. */ +#define TFTP_ERROR_EXISTS 6 /* File already exists. */ +#define TFTP_ERROR_NO_USER 7 /* No such user. */ + static EFI_PXE_BASE_CODE *pxe; static EFI_IP_ADDRESS tftp_addr; static CHAR8 *full_path; @@ -333,7 +343,33 @@ EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle UNUSED, CHAR8 *netbootname) return efi_status; } -EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle UNUSED, VOID **buffer, UINT64 *bufsiz) +/* Convert a TFTP error code to an EFI status code. */ +static EFI_STATUS +status_from_error(UINT8 error_code) +{ + switch (error_code) { + case TFTP_ERROR_NOT_FOUND: + return EFI_NOT_FOUND; + case TFTP_ERROR_ACCESS: + case TFTP_ERROR_NO_USER: + return EFI_ACCESS_DENIED; + case TFTP_ERROR_NO_SPACE: + return EFI_VOLUME_FULL; + case TFTP_ERROR_ILLEGAL_OP: + return EFI_PROTOCOL_ERROR; + case TFTP_ERROR_UNKNOWN_ID: + return EFI_INVALID_PARAMETER; + case TFTP_ERROR_EXISTS: + return EFI_WRITE_PROTECTED; + case TFTP_ERROR_NOT_DEFINED: + default: + /* Use a generic TFTP error for anything else. */ + return EFI_TFTP_ERROR; + } +} + +EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle UNUSED, VOID **buffer, + UINT64 *bufsiz, int flags) { EFI_STATUS efi_status; EFI_PXE_BASE_CODE_TFTP_OPCODE read = EFI_PXE_BASE_CODE_TFTP_READ_FILE; @@ -341,7 +377,8 @@ EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle UNUSED, VOID **buffer, UINT BOOLEAN nobuffer = FALSE; UINTN blksz = 512; - console_print(L"Fetching Netboot Image %a\n", full_path); + if (~flags & SUPPRESS_NETBOOT_OPEN_FAILURE_NOISE) + console_print(L"Fetching Netboot Image %a\n", full_path); if (*buffer == NULL) { *buffer = AllocatePool(4096 * 1024); if (!*buffer) @@ -362,8 +399,31 @@ try_again: goto try_again; } - if (EFI_ERROR(efi_status) && *buffer) { - FreePool(*buffer); + if (EFI_ERROR(efi_status)) { + if (pxe->Mode->TftpErrorReceived) { + if (~flags & SUPPRESS_NETBOOT_OPEN_FAILURE_NOISE) + console_print(L"TFTP error %u: %a\n", + pxe->Mode->TftpError.ErrorCode, + pxe->Mode->TftpError.ErrorString); + + efi_status = status_from_error(pxe->Mode->TftpError.ErrorCode); + } else if (efi_status == EFI_TFTP_ERROR) { + /* + * Unfortunately, some firmware doesn't fill in the + * error details. Treat all TFTP errors like file not + * found so shim falls back to the default loader. + * + * https://github.com/tianocore/edk2/pull/6287 + */ + if (~flags & SUPPRESS_NETBOOT_OPEN_FAILURE_NOISE) + console_print(L"Unknown TFTP error, treating " + "as file not found\n"); + efi_status = EFI_NOT_FOUND; + } + + if (*buffer) { + FreePool(*buffer); + } } return efi_status; } |
