From f309d7a7b78eec10621bc71f9401d5b9257f9f39 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 28 Feb 2021 13:45:58 +0000 Subject: [linux] Use host glibc system call wrappers When building as a Linux userspace application, iPXE currently implements its own system calls to the host kernel rather than relying on the host's C library. The output binary is statically linked and has no external dependencies. This matches the general philosophy of other platforms on which iPXE runs, since there are no external libraries available on either BIOS or UEFI bare metal. However, it would be useful for the Linux userspace application to be able to link against host libraries such as libslirp. Modify the build process to perform a two-stage link: first picking out the requested objects in the usual way from blib.a but with relocations left present, then linking again with a helper object to create a standard hosted application. The helper object provides the standard main() entry point and wrappers for the Linux system calls required by the iPXE Linux drivers and interface code. Signed-off-by: Michael Brown --- src/interface/linux/linux_smbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/interface/linux/linux_smbios.c') diff --git a/src/interface/linux/linux_smbios.c b/src/interface/linux/linux_smbios.c index 6e5174d23..494a60bd9 100644 --- a/src/interface/linux/linux_smbios.c +++ b/src/interface/linux/linux_smbios.c @@ -20,7 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include -#include +#include #include #include -- cgit v1.2.3-55-g7522 From 2a2909cd1f55b2110bf8ef48b65816c9fae4637f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 2 Mar 2021 23:43:21 +0000 Subject: [linux] Use generic sysfs mechanism to read SMBIOS table Signed-off-by: Michael Brown --- src/include/ipxe/smbios.h | 1 + src/interface/linux/linux_smbios.c | 140 ++++++++++++++++++++----------------- src/interface/smbios/smbios.c | 10 +++ 3 files changed, 87 insertions(+), 64 deletions(-) (limited to 'src/interface/linux/linux_smbios.c') diff --git a/src/include/ipxe/smbios.h b/src/include/ipxe/smbios.h index 53fbd8cb8..42278fb24 100644 --- a/src/include/ipxe/smbios.h +++ b/src/include/ipxe/smbios.h @@ -235,5 +235,6 @@ extern int read_smbios_string ( struct smbios_structure *structure, unsigned int index, void *data, size_t len ); extern int smbios_version ( void ); +extern void smbios_clear ( void ); #endif /* _IPXE_SMBIOS_H */ diff --git a/src/interface/linux/linux_smbios.c b/src/interface/linux/linux_smbios.c index 494a60bd9..981873943 100644 --- a/src/interface/linux/linux_smbios.c +++ b/src/interface/linux/linux_smbios.c @@ -21,20 +21,21 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include +#include +#include #include -/** SMBIOS filename */ -static const char smbios_filename[] = "/dev/mem"; - -/** SMBIOS entry point scan region start address */ -#define SMBIOS_ENTRY_START 0xf0000 +/** SMBIOS entry point filename */ +static const char smbios_entry_filename[] = + "/sys/firmware/dmi/tables/smbios_entry_point"; -/** SMBIOS entry point scan region length */ -#define SMBIOS_ENTRY_LEN 0x10000 +/** SMBIOS filename */ +static const char smbios_filename[] = "/sys/firmware/dmi/tables/DMI"; -/** SMBIOS mapping alignment */ -#define SMBIOS_ALIGN 0x1000 +/** Cache SMBIOS data */ +static userptr_t smbios_data; /** * Find SMBIOS @@ -43,73 +44,84 @@ static const char smbios_filename[] = "/dev/mem"; * @ret rc Return status code */ static int linux_find_smbios ( struct smbios *smbios ) { - struct smbios_entry entry; - void *entry_mem; - void *smbios_mem; - size_t smbios_offset; - size_t smbios_indent; - size_t smbios_len; - int fd; + struct smbios3_entry *smbios3_entry; + struct smbios_entry *smbios_entry; + userptr_t entry; + void *data; + int len; int rc; - /* Open SMBIOS file */ - fd = linux_open ( smbios_filename, O_RDONLY ); - if ( fd < 0 ) { - rc = -ELINUX ( linux_errno ); - DBGC ( smbios, "SMBIOS could not open %s: %s\n", - smbios_filename, linux_strerror ( linux_errno ) ); - goto err_open; + /* Read entry point file */ + len = linux_sysfs_read ( smbios_entry_filename, &entry ); + if ( len < 0 ) { + rc = len; + DBGC ( smbios, "SMBIOS could not read %s: %s\n", + smbios_entry_filename, strerror ( rc ) ); + goto err_entry; } - - /* Map the region potentially containing the SMBIOS entry point */ - entry_mem = linux_mmap ( NULL, SMBIOS_ENTRY_LEN, PROT_READ, MAP_SHARED, - fd, SMBIOS_ENTRY_START ); - if ( entry_mem == MAP_FAILED ) { - rc = -ELINUX ( linux_errno ); - DBGC ( smbios, "SMBIOS could not mmap %s (%#x+%#x): %s\n", - smbios_filename, SMBIOS_ENTRY_START, SMBIOS_ENTRY_LEN, - linux_strerror ( linux_errno ) ); - goto err_mmap_entry; + data = user_to_virt ( entry, 0 ); + smbios3_entry = data; + smbios_entry = data; + if ( ( len >= ( ( int ) sizeof ( *smbios3_entry ) ) ) && + ( smbios3_entry->signature == SMBIOS3_SIGNATURE ) ) { + smbios->version = SMBIOS_VERSION ( smbios3_entry->major, + smbios3_entry->minor ); + } else if ( ( len >= ( ( int ) sizeof ( *smbios_entry ) ) ) && + ( smbios_entry->signature == SMBIOS_SIGNATURE ) ) { + smbios->version = SMBIOS_VERSION ( smbios_entry->major, + smbios_entry->minor ); + } else { + DBGC ( smbios, "SMBIOS invalid entry point %s:\n", + smbios_entry_filename ); + DBGC_HDA ( smbios, 0, data, len ); + rc = -EINVAL; + goto err_version; } - /* Scan for the SMBIOS entry point */ - if ( ( rc = find_smbios_entry ( virt_to_user ( entry_mem ), - SMBIOS_ENTRY_LEN, &entry ) ) != 0 ) - goto err_find_entry; - - /* Map the region containing the SMBIOS structures */ - smbios_indent = ( entry.smbios_address & ( SMBIOS_ALIGN - 1 ) ); - smbios_offset = ( entry.smbios_address - smbios_indent ); - smbios_len = ( entry.smbios_len + smbios_indent ); - smbios_mem = linux_mmap ( NULL, smbios_len, PROT_READ, MAP_SHARED, - fd, smbios_offset ); - if ( smbios_mem == MAP_FAILED ) { - rc = -ELINUX ( linux_errno ); - DBGC ( smbios, "SMBIOS could not mmap %s (%#zx+%#zx): %s\n", - smbios_filename, smbios_offset, smbios_len, - linux_strerror ( linux_errno ) ); - goto err_mmap_smbios; + /* Read SMBIOS file */ + len = linux_sysfs_read ( smbios_filename, &smbios_data ); + if ( len < 0 ) { + rc = len; + DBGC ( smbios, "SMBIOS could not read %s: %s\n", + smbios_filename, strerror ( rc ) ); + goto err_read; } - /* Fill in entry point descriptor structure */ - smbios->address = virt_to_user ( smbios_mem + smbios_indent ); - smbios->len = entry.smbios_len; - smbios->count = entry.smbios_count; - smbios->version = SMBIOS_VERSION ( entry.major, entry.minor ); + /* Populate SMBIOS descriptor */ + smbios->address = smbios_data; + smbios->len = len; + smbios->count = 0; - /* Unmap the entry point region (no longer required) */ - linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN ); + /* Free entry point */ + ufree ( entry ); return 0; - linux_munmap ( smbios_mem, smbios_len ); - err_mmap_smbios: - err_find_entry: - linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN ); - err_mmap_entry: - linux_close ( fd ); - err_open: + ufree ( smbios_data ); + err_read: + err_version: + ufree ( entry ); + err_entry: return rc; } +/** + * Free cached SMBIOS data + * + */ +static void linux_smbios_shutdown ( int booting __unused ) { + + /* Clear SMBIOS data pointer */ + smbios_clear(); + + /* Free SMBIOS data */ + ufree ( smbios_data ); +} + +/** SMBIOS shutdown function */ +struct startup_fn linux_smbios_startup_fn __startup_fn ( STARTUP_NORMAL ) = { + .name = "linux_smbios", + .shutdown = linux_smbios_shutdown, +}; + PROVIDE_SMBIOS ( linux, find_smbios, linux_find_smbios ); diff --git a/src/interface/smbios/smbios.c b/src/interface/smbios/smbios.c index 5bd76f16a..12a080da2 100644 --- a/src/interface/smbios/smbios.c +++ b/src/interface/smbios/smbios.c @@ -255,3 +255,13 @@ int smbios_version ( void ) { return smbios.version; } + +/** + * Clear SMBIOS entry point descriptor + * + */ +void smbios_clear ( void ) { + + /* Clear address */ + smbios.address = UNULL; +} -- cgit v1.2.3-55-g7522