Skip to content

Commit 1b02ba2

Browse files
committed
ipxe: Allow next loader path to be derived from shim path
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]>
1 parent 4048a55 commit 1b02ba2

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

httpboot.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ generate_next_uri (CONST CHAR8 *current_uri, CONST CHAR8 *next_loader,
220220
ptr++;
221221
}
222222

223+
if((*uri = automatic_next_path(current_uri, 0, next_loader)))
224+
return EFI_SUCCESS;
225+
223226
*uri = AllocatePool(sizeof(CHAR8) * (path_len + next_len + 1));
224227
if (!*uri)
225228
return EFI_OUT_OF_RESOURCES;

netboot.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ static BOOLEAN extract_tftp_info(CHAR8 *url, CHAR8 *name)
243243
FreePool(template);
244244
return FALSE;
245245
}
246+
if ((full_path = automatic_next_path(end, 0, name))) {
247+
FreePool(template);
248+
return TRUE;
249+
}
246250
full_path = AllocateZeroPool(strlen(end)+strlen(template)+1);
247251
if (!full_path) {
248252
FreePool(template);
@@ -309,6 +313,12 @@ static EFI_STATUS parseDhcp4(CHAR8 *name)
309313
INTN i;
310314
UINT8 *dir = pkt_v4->BootpBootFile;
311315

316+
if ((full_path = automatic_next_path((CHAR8 *)dir, dir_len, name))) {
317+
memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4);
318+
FreePool(template);
319+
return EFI_SUCCESS;
320+
}
321+
312322
for (i = dir_len; i >= 0; i--) {
313323
if ((dir[i] == '/') || (dir[i] == '\\'))
314324
break;

shim.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,3 +1307,59 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
13071307
devel_egress(EFI_ERROR(efi_status) ? EXIT_FAILURE : EXIT_SUCCESS);
13081308
return efi_status;
13091309
}
1310+
1311+
/*
1312+
* If we are attempting to download the default loader, then construct
1313+
* the path by changing "-shim[arch].efi" to ".efi", if possible.
1314+
*
1315+
* This code is maintained as a patch separate from the shim codebase,
1316+
* and so is deliberately optimised for minimal intrusiveness rather
1317+
* than elegance.
1318+
*
1319+
*/
1320+
CHAR8 *automatic_next_path(CONST CHAR8 *path, UINTN path_len,
1321+
CONST CHAR8 *maybe_loader)
1322+
{
1323+
CHAR8 *filename;
1324+
CHAR8 *hyphen;
1325+
CHAR8 *dot;
1326+
CHAR8 *next;
1327+
1328+
/* Check if this request is for the default loader */
1329+
if (strcmp(maybe_loader, DEFAULT_LOADER_CHAR) != 0) {
1330+
/* Not the default loader: use normal shim code path */
1331+
return NULL;
1332+
}
1333+
1334+
/* Copy and NUL-terminate the path */
1335+
if (!path_len)
1336+
path_len = strlen(path);
1337+
next = AllocateZeroPool(path_len + 1);
1338+
if (!next)
1339+
return NULL;
1340+
memcpy(next, path, path_len);
1341+
next[path_len] = '\0';
1342+
1343+
/* Locate filename portion of path */
1344+
filename = strrchr(next, '/');
1345+
if (filename) {
1346+
filename++;
1347+
} else {
1348+
filename = next;
1349+
}
1350+
1351+
/* Check for "-shim[arch].efi" suffix */
1352+
if ((hyphen = strrchr(filename, '-')) &&
1353+
(strncasecmp(hyphen, "-shim", 5) == 0) &&
1354+
(dot = strrchr(hyphen, '.')) &&
1355+
(strcasecmp(dot, ".efi") == 0) &&
1356+
(dot - hyphen <= 9)) {
1357+
/* Suffix is present: replace "-shim[arch]" with ".efi" */
1358+
strcpy(hyphen, dot);
1359+
return next;
1360+
}
1361+
1362+
/* Suffix not found: use normal shim code path */
1363+
FreePool(next);
1364+
return NULL;
1365+
}

shim.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,7 @@ typedef struct {
335335
EFI_DEVICE_PATH *loaded_image_device_path;
336336
} SHIM_LOADED_IMAGE;
337337

338+
extern CHAR8 *automatic_next_path(CONST CHAR8 *path, UINTN path_len,
339+
CONST CHAR8 *maybe_loader);
340+
338341
#endif /* SHIM_H_ */

0 commit comments

Comments
 (0)