Compare commits

...

6 Commits

Author SHA1 Message Date
f4f9adf618 [efi] Include Secure Boot Advanced Targeting (SBAT) metadata
SBAT defines an encoding for security generation numbers stored as a
CSV file within a special ".sbat" section in the signed binary.  If a
Secure Boot exploit is discovered then the generation number will be
incremented alongside the corresponding fix.

Platforms may then record the minimum generation number required for
any given product.  This allows for an efficient revocation mechanism
that consumes minimal flash storage space (in contrast to the DBX
mechanism, which allows for only a single-digit number of revocation
events to ever take place across all possible signed binaries).

Add SBAT metadata to iPXE EFI binaries to support this mechanism.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2022-01-13 14:12:44 +00:00
fbbdc39260 [build] Ensure version.%.o is always rebuilt as expected
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2022-01-13 13:43:08 +00:00
53a5de3641 [doc] Update user-visible ipxe.org URIs to use HTTPS
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2022-01-13 12:48:38 +00:00
91c77e2592 [efi] Do not align VirtualSize for .reloc and .debug sections
As of commit f1e9e2b ("[efi] Align EFI image sections by page size"),
the VirtualSize fields for the .reloc and .debug sections have been
rounded up to the (4kB) image alignment.  This breaks the PE
relocation logic in the UEFI shim, which requires the VirtualSize
field to exactly match the size as recorded in the data directory.

Fix by setting the VirtualSize field to the unaligned size of the
section, as is already done for normal PE sections (i.e. those other
than .reloc and .debug).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2022-01-11 15:27:14 +00:00
f43c2fd697 [settings] Support formatting UUIDs as little-endian GUIDs
The RFC4122 specification defines UUIDs as being in network byte
order, but an unfortunately significant amount of (mostly Microsoft)
software treats them as having the first three fields in little-endian
byte order.

In an ideal world, any server-side software that compares UUIDs for
equality would perform an endian-insensitive comparison (analogous to
comparing strings for equality using a case-insensitive comparison),
and would therefore not care about byte order differences.

Define a setting type name ":guid" to allow a UUID setting to be
formatted in little-endian order, to simplify interoperability with
server-side software that expects such a formatting.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2022-01-04 14:03:12 +00:00
9062544f6a [efi] Disable EFI watchdog timer when shutting down to boot an OS
The UEFI specification mandates that the EFI watchdog timer should be
disabled by the platform firmware as part of the ExitBootServices()
call, but some platforms (e.g. Hyper-V) are observed to occasionally
forget to do so, resulting in a reboot approximately five minutes
after starting the operating system.

Work around these firmware bugs by disabling the watchdog timer
ourselves.

Requested-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Tested-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-11-25 09:30:59 +00:00
22 changed files with 235 additions and 37 deletions

View File

@ -190,7 +190,7 @@ vmware : bin/8086100f.mrom bin/808610d3.mrom bin/10222000.rom bin/15ad07b0.rom
@$(ECHO) ' bin/10222000.rom -- vlance/pcnet32'
@$(ECHO) ' bin/15ad07b0.rom -- vmxnet3'
@$(ECHO)
@$(ECHO) 'For more information, see http://ipxe.org/howto/vmware'
@$(ECHO) 'For more information, see https://ipxe.org/howto/vmware'
@$(ECHO)
@$(ECHO) '==========================================================='

View File

@ -918,7 +918,7 @@ $(BIN)/deps/%.d : % $(MAKEDEPS)
# Calculate list of dependency files
#
AUTO_DEPS = $(patsubst %,$(BIN)/deps/%.d,$(AUTO_SRCS))
AUTO_DEPS = $(patsubst %,$(BIN)/deps/%.d,$(AUTO_SRCS) core/version.c)
autodeps :
@$(ECHO) $(AUTO_DEPS)
VERYCLEANUP += $(BIN)/deps
@ -1202,7 +1202,7 @@ endif
# Build version
#
GIT_INDEX := $(if $(GITVERSION),$(if $(wildcard ../.git/index),../.git/index))
$(BIN)/version.%.o : core/version.c $(MAKEDEPS) $(GIT_INDEX)
$(BIN)/version.%.o : core/version.c $(MAKEDEPS) $(version_DEPS) $(GIT_INDEX)
$(QM)$(ECHO) " [VERSION] $@"
$(Q)$(COMPILE_c) -DBUILD_NAME="\"$*\"" \
-DVERSION_MAJOR=$(VERSION_MAJOR) \

View File

@ -136,6 +136,8 @@ SECTIONS {
*(.note.*)
*(.discard)
*(.discard.*)
*(.sbat)
*(.sbat.*)
}
/*

View File

@ -100,5 +100,7 @@ SECTIONS {
*(.rel.*)
*(.discard)
*(.discard.*)
*(.sbat)
*(.sbat.*)
}
}

View File

@ -47,7 +47,7 @@ static char __bss16_array ( syslinux_version, [32] );
#define syslinux_version __use_data16 ( syslinux_version )
/** The "SYSLINUX" copyright string */
static char __data16_array ( syslinux_copyright, [] ) = " http://ipxe.org";
static char __data16_array ( syslinux_copyright, [] ) = " https://ipxe.org";
#define syslinux_copyright __use_data16 ( syslinux_copyright )
static char __data16_array ( syslinux_configuration_file, [] ) = "";

View File

@ -161,7 +161,7 @@ pnpheader:
/* Manufacturer string */
mfgstr:
.asciz "http://ipxe.org"
.asciz "https://ipxe.org"
.size mfgstr, . - mfgstr
/* Product string
@ -607,7 +607,7 @@ get_pmm_decompress_to:
* strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/branding.h.
*
* While nothing in the GPL prevents you from removing all references
* to iPXE or http://ipxe.org, we prefer you not to do so.
* to iPXE or https://ipxe.org, we prefer you not to do so.
*
* If you have an OEM-mandated branding requirement that cannot be
* satisfied simply by defining PRODUCT_NAME and PRODUCT_SHORT_NAME,

View File

@ -229,6 +229,8 @@ SECTIONS {
*(.einfo.*)
*(.discard)
*(.discard.*)
*(.sbat)
*(.sbat.*)
}
/*

View File

@ -24,6 +24,8 @@ SECTIONS {
*(.einfo.*)
*(.discard)
*(.discard.*)
*(.sbat)
*(.sbat.*)
}
}

View File

@ -100,5 +100,7 @@ SECTIONS {
*(.rel.*)
*(.discard)
*(.discard.*)
*(.sbat)
*(.sbat.*)
}
}

View File

@ -26,7 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
#define PRODUCT_NAME ""
#define PRODUCT_SHORT_NAME "iPXE"
#define PRODUCT_URI "http://ipxe.org"
#define PRODUCT_URI "https://ipxe.org"
/*
* Tag line
@ -44,15 +44,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* (e.g. "Permission denied") and a 32-bit error number. This number
* is incorporated into an error URI such as
*
* "No such file or directory (http://ipxe.org/2d0c613b)"
* "No such file or directory (https://ipxe.org/2d0c613b)"
*
* or
*
* "Operation not supported (http://ipxe.org/3c092003)"
* "Operation not supported (https://ipxe.org/3c092003)"
*
* Users may browse to the URI within the error message, which is
* provided by a database running on the iPXE web site
* (http://ipxe.org). This database provides details for all possible
* (https://ipxe.org). This database provides details for all possible
* errors generated by iPXE, including:
*
* - the detailed error message (e.g. "Not an OCSP signing
@ -74,13 +74,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* If you have a customer support team and would like your customers
* to contact your support team for all problems, instead of using the
* existing support infrastructure provided by http://ipxe.org, then
* existing support infrastructure provided by https://ipxe.org, then
* you may define a custom URI to be included within error messages.
*
* Note that the custom URI is a printf() format string which must
* include a format specifier for the 32-bit error number.
*/
#define PRODUCT_ERROR_URI "http://ipxe.org/%08x"
#define PRODUCT_ERROR_URI "https://ipxe.org/%08x"
/*
* Command help messages
@ -88,7 +88,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* iPXE command help messages include a URI constructed from the
* command name, such as
*
* "See http://ipxe.org/cmd/vcreate for further information"
* "See https://ipxe.org/cmd/vcreate for further information"
*
* The iPXE web site includes documentation for the commands provided
* by the iPXE shell, including:
@ -113,7 +113,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* If you want to provide your own documentation for all of the
* commands provided by the iPXE shell, rather than using the existing
* support infrastructure provided by http://ipxe.org, then you may
* support infrastructure provided by https://ipxe.org, then you may
* define a custom URI to be included within command help messages.
*
* Note that the custom URI is a printf() format string which must
@ -124,7 +124,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* iPXE project and prohibit the alteration or removal of any
* references to "iPXE". ]
*/
#define PRODUCT_COMMAND_URI "http://ipxe.org/cmd/%s"
#define PRODUCT_COMMAND_URI "https://ipxe.org/cmd/%s"
/*
* Setting help messages
@ -132,7 +132,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* iPXE setting help messages include a URI constructed from the
* setting name, such as
*
* "http://ipxe.org/cfg/initiator-iqn"
* "https://ipxe.org/cfg/initiator-iqn"
*
* The iPXE web site includes documentation for the settings used by
* iPXE, including:
@ -156,7 +156,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* If you want to provide your own documentation for all of the
* settings used by iPXE, rather than using the existing support
* infrastructure provided by http://ipxe.org, then you may define a
* infrastructure provided by https://ipxe.org, then you may define a
* custom URI to be included within setting help messages.
*
* Note that the custom URI is a printf() format string which must
@ -167,7 +167,25 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* iPXE project and prohibit the alteration or removal of any
* references to "iPXE". ]
*/
#define PRODUCT_SETTING_URI "http://ipxe.org/cfg/%s"
#define PRODUCT_SETTING_URI "https://ipxe.org/cfg/%s"
/*
* Product security name suffix
*
* Vendors creating signed iPXE binaries must set this to a non-empty
* value (e.g. "2pint").
*/
#define PRODUCT_SBAT_NAME ""
/*
* Product security generation
*
* Vendors creating signed iPXE binaries must set this to a non-zero
* value, and must increment the value whenever a Secure Boot exploit
* is fixed (unless the upstream IPXE_SBAT_GENERATION has already been
* incremented as part of that fix).
*/
#define PRODUCT_SBAT_GENERATION 0
#include <config/local/branding.h>

View File

@ -2199,7 +2199,7 @@ const struct setting_type setting_type_base64 __setting_type = {
};
/**
* Format UUID setting value
* Format UUID/GUID setting value
*
* @v type Setting type
* @v raw Raw setting value
@ -2208,17 +2208,24 @@ const struct setting_type setting_type_base64 __setting_type = {
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
static int format_uuid_setting ( const struct setting_type *type __unused,
static int format_uuid_setting ( const struct setting_type *type,
const void *raw, size_t raw_len, char *buf,
size_t len ) {
const union uuid *uuid = raw;
union uuid uuid;
/* Range check */
if ( raw_len != sizeof ( *uuid ) )
if ( raw_len != sizeof ( uuid ) )
return -ERANGE;
/* Copy value */
memcpy ( &uuid, raw, sizeof ( uuid ) );
/* Mangle GUID byte ordering */
if ( type == &setting_type_guid )
uuid_mangle ( &uuid );
/* Format value */
return snprintf ( buf, len, "%s", uuid_ntoa ( uuid ) );
return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
}
/** UUID setting type */
@ -2227,6 +2234,12 @@ const struct setting_type setting_type_uuid __setting_type = {
.format = format_uuid_setting,
};
/** GUID setting type */
const struct setting_type setting_type_guid __setting_type = {
.name = "guid",
.format = format_uuid_setting,
};
/**
* Format PCI bus:dev.fn setting value
*

View File

@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <wchar.h>
#include <ipxe/features.h>
#include <ipxe/version.h>
#include <ipxe/sbat.h>
#include <config/general.h>
#include <config/branding.h>
@ -92,3 +93,32 @@ const wchar_t build_wname[] = WSTRING ( BUILD_NAME );
/** Copy of build name string within ".prefix" */
const char build_name_prefix[] __attribute__ (( section ( ".prefix.name" ) ))
= BUILD_NAME;
/** SBAT upstream iPXE line
*
* This line represents the security generation of the upstream
* codebase from which this build is derived.
*/
#define SBAT_IPXE \
SBAT_LINE ( "ipxe", IPXE_SBAT_GENERATION, \
"iPXE", BUILD_NAME, VERSION, "https://ipxe.org" )
/** SBAT local build line
*
* This line states the security generation of the local build, which
* may include non-default features or non-upstreamed modifications.
*/
#if PRODUCT_SBAT_GENERATION
#define SBAT_PRODUCT \
SBAT_LINE ( "ipxe." PRODUCT_SBAT_NAME, PRODUCT_SBAT_GENERATION, \
PRODUCT_SHORT_NAME, BUILD_NAME, VERSION, \
PRODUCT_URI )
#else
#define SBAT_PRODUCT ""
#endif
/** SBAT data */
#define SBAT_DATA SBAT_HEADER "" SBAT_IPXE "" SBAT_PRODUCT
/** SBAT data (without any NUL terminator) */
const char sbat[ sizeof ( SBAT_DATA ) - 1 ] __sbat = SBAT_DATA;

68
src/include/ipxe/sbat.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef _IPXE_SBAT_H
#define _IPXE_SBAT_H
/** @file
*
* Secure Boot Advanced Targeting (SBAT)
*
* SBAT defines an encoding for security generation numbers stored as
* a CSV file within a special ".sbat" section in the signed binary.
* If a Secure Boot exploit is discovered then the generation number
* will be incremented alongside the corresponding fix.
*
* Platforms may then record the minimum generation number required
* for any given product. This allows for an efficient revocation
* mechanism that consumes minimal flash storage space (in contrast to
* the DBX mechanism, which allows for only a single-digit number of
* revocation events to ever take place across all possible signed
* binaries).
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* A single line within an SBAT CSV file
*
* @v name Machine-readable component name
* @v generation Security generation number
* @v vendor Human-readable vendor name
* @v package Human-readable package name
* @v version Human-readable package version
* @v uri Contact URI
* @ret line CSV line
*/
#define SBAT_LINE( name, generation, vendor, package, version, uri ) \
name "," _S2 ( generation ) "," vendor "," package "," \
version "," uri "\n"
/** SBAT format generation */
#define SBAT_GENERATION 1
/** Upstream security generation
*
* This represents the security generation of the upstream codebase.
* It will be incremented whenever a Secure Boot exploit is fixed in
* the upstream codebase.
*
* If you do not have commit access to the upstream iPXE repository,
* then you may not modify this value under any circumstances.
*/
#define IPXE_SBAT_GENERATION 1
/* Seriously, do not modify this value */
#if IPXE_SBAT_GENERATION != 1
#error "You may not modify IPXE_SBAT_GENERATION"
#endif
/** SBAT header line */
#define SBAT_HEADER \
SBAT_LINE ( "sbat", SBAT_GENERATION, "SBAT Version", "sbat", \
_S2 ( SBAT_GENERATION ), \
"https://github.com/rhboot/shim/blob/main/SBAT.md" )
/** Mark variable as being in the ".sbat" section */
#define __sbat __attribute__ (( section ( ".sbat" ), aligned ( 512 ) ))
extern const char sbat[] __sbat;
#endif /* _IPXE_SBAT_H */

View File

@ -426,6 +426,7 @@ extern const struct setting_type setting_type_hexhyp __setting_type;
extern const struct setting_type setting_type_hexraw __setting_type;
extern const struct setting_type setting_type_base64 __setting_type;
extern const struct setting_type setting_type_uuid __setting_type;
extern const struct setting_type setting_type_guid __setting_type;
extern const struct setting_type setting_type_busdevfn __setting_type;
extern const struct setting_type setting_type_dnssl __setting_type;

View File

@ -774,7 +774,7 @@ struct srp_aer_rsp {
* The working draft specification for the SRP boot firmware table can
* be found at
*
* http://ipxe.org/wiki/srp/sbft
* https://ipxe.org/wiki/srp/sbft
*
*****************************************************************************
*/

View File

@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <ipxe/retry.h>
#include <ipxe/timer.h>
#include <ipxe/init.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_watchdog.h>
@ -80,3 +81,36 @@ static void efi_watchdog_expired ( struct retry_timer *timer,
/** Watchdog holdoff timer */
struct retry_timer efi_watchdog = TIMER_INIT ( efi_watchdog_expired );
/**
* Disable watching when shutting down to boot an operating system
*
* @v booting System is shutting down for OS boot
*/
static void efi_watchdog_shutdown ( int booting ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_STATUS efirc;
int rc;
/* If we are shutting down to boot an operating system, then
* disable the boot services watchdog timer. The UEFI
* specification mandates that the platform firmware does this
* as part of the ExitBootServices() call, but some platforms
* (e.g. Hyper-V) are observed to occasionally forget to do
* so, resulting in a reboot approximately five minutes after
* starting the operating system.
*/
if ( booting &&
( ( efirc = bs->SetWatchdogTimer ( 0, 0, 0, NULL ) ) != 0 ) ) {
rc = -EEFI ( efirc );
DBGC ( &efi_watchdog, "EFI could not disable watchdog timer: "
"%s\n", strerror ( rc ) );
/* Nothing we can do */
}
}
/** Watchdog startup/shutdown function */
struct startup_fn efi_watchdog_startup_fn __startup_fn ( STARTUP_EARLY ) = {
.name = "efi_watchdog",
.shutdown = efi_watchdog_shutdown,
};

View File

@ -140,7 +140,8 @@ static int smbios_fetch ( struct settings *settings __unused,
* is 2.6 or higher; we match this behaviour.
*/
raw = &buf[tag_offset];
if ( ( setting->type == &setting_type_uuid ) &&
if ( ( ( setting->type == &setting_type_uuid ) ||
( setting->type == &setting_type_guid ) ) &&
( tag_len == sizeof ( uuid ) ) &&
( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) {
DBG ( "SMBIOS detected mangled UUID\n" );

View File

@ -74,6 +74,19 @@ SECTIONS {
_ebss = .;
}
/*
* The SBAT section
*
*/
. = ALIGN ( _page_align );
.sbat : {
_sbat = .;
KEEP(*(.sbat))
KEEP(*(.sbat.*))
_esbat = .;
}
/*
* Weak symbols that need zero values if not otherwise defined
*

View File

@ -250,6 +250,12 @@ static struct setting test_uuid_setting = {
.type = &setting_type_uuid,
};
/** Test GUID setting type */
static struct setting test_guid_setting = {
.name = "test_guid",
.type = &setting_type_guid,
};
/** Test PCI bus:dev.fn setting type */
static struct setting test_busdevfn_setting = {
.name = "test_busdevfn",
@ -419,6 +425,10 @@ static void settings_test_exec ( void ) {
RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8,
0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ),
"1a6a749d-0eda-461a-a87a-7cfe4fca4a57" );
fetchf_ok ( &test_settings, &test_guid_setting,
RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8,
0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ),
"9d746a1a-da0e-1a46-a87a-7cfe4fca4a57" );
/* "busdevfn" setting type (no store capability) */
fetchf_ok ( &test_settings, &test_busdevfn_setting,

View File

@ -579,8 +579,8 @@ int ipxe ( struct net_device *netdev ) {
* defining the string PRODUCT_NAME in config/branding.h.
*
* While nothing in the GPL prevents you from removing all
* references to iPXE or http://ipxe.org, we prefer you not to
* do so.
* references to iPXE or https://ipxe.org, we prefer you not
* to do so.
*
*/
printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD PRODUCT_SHORT_NAME " %s"

View File

@ -753,15 +753,13 @@ static struct pe_section *
create_reloc_section ( struct pe_header *pe_header,
struct pe_relocs *pe_reltab ) {
struct pe_section *reloc;
size_t section_rawsz;
size_t section_memsz;
size_t section_filesz;
EFI_IMAGE_DATA_DIRECTORY *relocdir;
/* Allocate PE section */
section_rawsz = output_pe_reltab ( pe_reltab, NULL );
section_filesz = efi_file_align ( section_rawsz );
section_memsz = efi_image_align ( section_rawsz );
section_memsz = output_pe_reltab ( pe_reltab, NULL );
section_filesz = efi_file_align ( section_memsz );
reloc = xmalloc ( sizeof ( *reloc ) + section_filesz );
memset ( reloc, 0, sizeof ( *reloc ) + section_filesz );
@ -782,11 +780,12 @@ create_reloc_section ( struct pe_header *pe_header,
/* Update file header details */
pe_header->nt.FileHeader.NumberOfSections++;
pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( reloc->hdr );
pe_header->nt.OptionalHeader.SizeOfImage += section_memsz;
pe_header->nt.OptionalHeader.SizeOfImage +=
efi_image_align ( section_memsz );
relocdir = &(pe_header->nt.OptionalHeader.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
relocdir->VirtualAddress = reloc->hdr.VirtualAddress;
relocdir->Size = section_rawsz;
relocdir->Size = section_memsz;
return reloc;
}
@ -824,8 +823,8 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) {
} *contents;
/* Allocate PE section */
section_memsz = efi_image_align ( sizeof ( *contents ) );
section_filesz = efi_file_align ( sizeof ( *contents ) );
section_memsz = sizeof ( *contents );
section_filesz = efi_file_align ( section_memsz );
debug = xmalloc ( sizeof ( *debug ) + section_filesz );
memset ( debug, 0, sizeof ( *debug ) + section_filesz );
contents = ( void * ) debug->contents;
@ -857,7 +856,8 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) {
/* Update file header details */
pe_header->nt.FileHeader.NumberOfSections++;
pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( debug->hdr );
pe_header->nt.OptionalHeader.SizeOfImage += section_memsz;
pe_header->nt.OptionalHeader.SizeOfImage +=
efi_image_align ( section_memsz );
debugdir = &(pe_header->nt.OptionalHeader.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
debugdir->VirtualAddress = debug->hdr.VirtualAddress;

View File

@ -565,7 +565,7 @@ EOM
return join("\n", @output);
}
# Output NIC list in DokuWiki format (for http://ipxe.org)
# Output NIC list in DokuWiki format (for https://ipxe.org)
sub format_nic_list_dokuwiki {
my ($nic_list, $column_names) = @_;
my @output;