Skip to content

Commit

Permalink
ipxe: Allow next loader path to be derived from shim path
Browse files Browse the repository at this point in the history
Allow loader path to be constructed from the path used to load the
shim itself, e.g.:

    ipxe-shimx64.efi      -> ipxe.efi
    ipxe-shimaa64.efi     -> ipxe.efi
    snponly-shimx64.efi   -> snponly.efi
    snponly-shimaa64.efi  -> snponly.efi

This reduces the complexity of using a signed shim binary to load
iPXE, which (unlike GRUB) has a variety of possible binary names
depending on the requested driver set.  For example, if a site uses
all three of ipxe.efi, intel.efi, and snponly.efi then symlinks can be
used to provide the appropriate shim files:

    # iPXE binaries
    /var/lib/tftpboot/ipxe.efi
    /var/lib/tftpboot/intel.efi
    /var/lib/tftpboot/snponly.efi

    # shim binary (from this repository)
    /var/lib/tftpboot/ipxe-shimx64.efi

    # shim symlinks
    /var/lib/tftpboot/intel-shimx64.efi -> ipxe-shimx64.efi
    /var/lib/tftpboot/snponly-shimx64.efi -> ipxe-shimx64.efi

Unlike the shim binary names, iPXE binary names do not conventionally
include a CPU architecture suffix such as "x64" or "aa64": the
expectation is that if multiple architectures are in use at a site,
then there will be one directory per architecture.  For example:

    /var/lib/tftpboot/x86_64/ipxe.efi
    /var/lib/tftpboot/x86_64/ipxe-shimx64.efi
    /var/lib/tftpboot/arm64/ipxe.efi
    /var/lib/tftpboot/arm64/ipxe-shimaa64.efi

Signed-off-by: Michael Brown <[email protected]>
  • Loading branch information
mcb30 committed Mar 19, 2024
1 parent ff35d64 commit 97cee9b
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 0 deletions.
3 changes: 3 additions & 0 deletions httpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ generate_next_uri (CONST CHAR8 *current_uri, CONST CHAR8 *next_loader,
ptr++;
}

if((*uri = automatic_next_path(current_uri, 0, next_loader)))
return EFI_SUCCESS;

*uri = AllocatePool(sizeof(CHAR8) * (path_len + next_len + 1));
if (!*uri)
return EFI_OUT_OF_RESOURCES;
Expand Down
10 changes: 10 additions & 0 deletions netboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ static BOOLEAN extract_tftp_info(CHAR8 *url, CHAR8 *name)
FreePool(template);
return FALSE;
}
if ((full_path = automatic_next_path(end, 0, name))) {
FreePool(template);
return TRUE;
}
full_path = AllocateZeroPool(strlen(end)+strlen(template)+1);
if (!full_path) {
FreePool(template);
Expand Down Expand Up @@ -276,6 +280,12 @@ static EFI_STATUS parseDhcp4(CHAR8 *name)
INTN i;
UINT8 *dir = pkt_v4->BootpBootFile;

if ((full_path = automatic_next_path((CHAR8 *)dir, dir_len, name))) {
memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4);
FreePool(template);
return EFI_SUCCESS;
}

for (i = dir_len; i >= 0; i--) {
if ((dir[i] == '/') || (dir[i] == '\\'))
break;
Expand Down
56 changes: 56 additions & 0 deletions shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -2004,3 +2004,59 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
devel_egress(EFI_ERROR(efi_status) ? EXIT_FAILURE : EXIT_SUCCESS);
return efi_status;
}

/*
* If we are attempting to download the default loader, then construct
* the path by changing "-shim[arch].efi" to ".efi", if possible.
*
* This code is maintained as a patch separate from the shim codebase,
* and so is deliberately optimised for minimal intrusiveness rather
* than elegance.
*
*/
CHAR8 *automatic_next_path(CONST CHAR8 *path, UINTN path_len,
CONST CHAR8 *maybe_loader)
{
CHAR8 *filename;
CHAR8 *hyphen;
CHAR8 *dot;
CHAR8 *next;

/* Check if this request is for the default loader */
if (strcmp(maybe_loader, DEFAULT_LOADER_CHAR) != 0) {
/* Not the default loader: use normal shim code path */
return NULL;
}

/* Copy and NUL-terminate the path */
if (!path_len)
path_len = strlen(path);
next = AllocateZeroPool(path_len + 1);
if (!next)
return NULL;
memcpy(next, path, path_len);
next[path_len] = '\0';

/* Locate filename portion of path */
filename = strrchr(next, '/');
if (filename) {
filename++;
} else {
filename = next;
}

/* Check for "-shim[arch].efi" suffix */
if ((hyphen = strrchr(filename, '-')) &&
(strncasecmp(hyphen, "-shim", 5) == 0) &&
(dot = strrchr(hyphen, '.')) &&
(strcasecmp(dot, ".efi") == 0) &&
(dot - hyphen <= 9)) {
/* Suffix is present: replace "-shim[arch]" with ".efi" */
strcpy(hyphen, dot);
return next;
}

/* Suffix not found: use normal shim code path */
FreePool(next);
return NULL;
}
3 changes: 3 additions & 0 deletions shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,7 @@ verify_buffer (char *data, int datasize,

char *translate_slashes(char *out, const char *str);

extern CHAR8 *automatic_next_path(CONST CHAR8 *path, UINTN path_len,
CONST CHAR8 *maybe_loader);

#endif /* SHIM_H_ */

0 comments on commit 97cee9b

Please sign in to comment.