summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/interface/linux
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/ipxe/src/interface/linux')
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_console.c155
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_entropy.c97
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_nap.c41
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_pci.c185
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_smbios.c115
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_time.c46
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_timer.c87
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_uaccess.c39
-rw-r--r--qemu/roms/ipxe/src/interface/linux/linux_umalloc.c154
9 files changed, 919 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_console.c b/qemu/roms/ipxe/src/interface/linux/linux_console.c
new file mode 100644
index 000000000..5105eaa94
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_console.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/** @file
+ *
+ * Linux console implementation.
+ *
+ */
+
+#include <ipxe/console.h>
+
+#include <ipxe/init.h>
+#include <ipxe/keys.h>
+#include <linux_api.h>
+
+#include <linux/termios.h>
+#include <asm/errno.h>
+
+#include <config/console.h>
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_LINUX ) && CONSOLE_EXPLICIT ( CONSOLE_LINUX ) )
+#undef CONSOLE_LINUX
+#define CONSOLE_LINUX ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
+#endif
+
+static void linux_console_putchar(int c)
+{
+ /* write to stdout */
+ if (linux_write(1, &c, 1) != 1)
+ DBG("linux_console write failed (%s)\n", linux_strerror(linux_errno));
+}
+
+static int linux_console_getchar()
+{
+ char c;
+
+ /* read from stdin */
+ if (linux_read(0, &c, 1) < 0) {
+ DBG("linux_console read failed (%s)\n", linux_strerror(linux_errno));
+ return 0;
+ }
+ /* backspace seems to be returned as ascii del, map it here */
+ if (c == 0x7f)
+ return KEY_BACKSPACE;
+ else
+ return c;
+}
+
+static int linux_console_iskey()
+{
+ struct pollfd pfd;
+ pfd.fd = 0;
+ pfd.events = POLLIN;
+
+ /* poll for data to be read on stdin */
+ if (linux_poll(&pfd, 1, 0) == -1) {
+ DBG("linux_console poll failed (%s)\n", linux_strerror(linux_errno));
+ return 0;
+ }
+
+ if (pfd.revents & POLLIN)
+ return 1;
+ else
+ return 0;
+}
+
+struct console_driver linux_console __console_driver = {
+ .disabled = 0,
+ .putchar = linux_console_putchar,
+ .getchar = linux_console_getchar,
+ .iskey = linux_console_iskey,
+ .usage = CONSOLE_LINUX,
+};
+
+static int linux_tcgetattr(int fd, struct termios *termios_p)
+{
+ return linux_ioctl(fd, TCGETS, termios_p);
+}
+
+static int linux_tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
+{
+ unsigned long int cmd;
+
+ switch (optional_actions)
+ {
+ case TCSANOW:
+ cmd = TCSETS;
+ break;
+ case TCSADRAIN:
+ cmd = TCSETSW;
+ break;
+ case TCSAFLUSH:
+ cmd = TCSETSF;
+ break;
+ default:
+ linux_errno = EINVAL;
+ return -1;
+ }
+
+ return linux_ioctl(fd, cmd, termios_p);
+}
+
+/** Saved termios attributes */
+static struct termios saved_termios;
+
+/** Setup the terminal for our use */
+static void linux_console_startup(void)
+{
+ struct termios t;
+
+ if (linux_tcgetattr(0, &t)) {
+ DBG("linux_console tcgetattr failed (%s)", linux_strerror(linux_errno));
+ return;
+ }
+
+ saved_termios = t;
+
+ /* Disable canonical mode and echo. Let readline handle that */
+ t.c_lflag &= ~(ECHO | ICANON);
+ /* stop ^C from sending a signal */
+ t.c_cc[VINTR] = 0;
+
+ if (linux_tcsetattr(0, TCSAFLUSH, &t))
+ DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno));
+}
+
+/** Restores original terminal attributes on shutdown */
+static void linux_console_shutdown(int flags __unused)
+{
+ if (linux_tcsetattr(0, TCSAFLUSH, &saved_termios))
+ DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno));
+}
+
+struct startup_fn linux_console_startup_fn __startup_fn(STARTUP_EARLY) = {
+ .startup = linux_console_startup,
+ .shutdown = linux_console_shutdown,
+};
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_entropy.c b/qemu/roms/ipxe/src/interface/linux/linux_entropy.c
new file mode 100644
index 000000000..4671a48da
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_entropy.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Linux entropy source
+ *
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <linux_api.h>
+#include <ipxe/entropy.h>
+
+/** Entropy source filename */
+static const char entropy_filename[] = "/dev/random";
+
+/** Entropy source file handle */
+static int entropy_fd;
+
+/**
+ * Enable entropy gathering
+ *
+ * @ret rc Return status code
+ */
+static int linux_entropy_enable ( void ) {
+
+ /* Open entropy source */
+ entropy_fd = linux_open ( entropy_filename, O_RDONLY );
+ if ( entropy_fd < 0 ) {
+ DBGC ( &entropy_fd, "ENTROPY could not open %s: %s\n",
+ entropy_filename, linux_strerror ( linux_errno ) );
+ return entropy_fd;
+ }
+
+ return 0;
+}
+
+/**
+ * Disable entropy gathering
+ *
+ */
+static void linux_entropy_disable ( void ) {
+
+ /* Close entropy source */
+ linux_close ( entropy_fd );
+}
+
+/**
+ * Get noise sample
+ *
+ * @ret noise Noise sample
+ * @ret rc Return status code
+ */
+static int linux_get_noise ( noise_sample_t *noise ) {
+ uint8_t byte;
+ ssize_t len;
+
+ /* Read a single byte from entropy source */
+ len = linux_read ( entropy_fd, &byte, sizeof ( byte ) );
+ if ( len < 0 ) {
+ DBGC ( &entropy_fd, "ENTROPY could not read from %s: %s\n",
+ entropy_filename, linux_strerror ( linux_errno ) );
+ return len;
+ }
+ if ( len == 0 ) {
+ DBGC ( &entropy_fd, "ENTROPY EOF on reading from %s: %s\n",
+ entropy_filename, linux_strerror ( linux_errno ) );
+ return -EPIPE;
+ }
+ *noise = byte;
+
+ return 0;
+}
+
+PROVIDE_ENTROPY_INLINE ( linux, min_entropy_per_sample );
+PROVIDE_ENTROPY ( linux, entropy_enable, linux_entropy_enable );
+PROVIDE_ENTROPY ( linux, entropy_disable, linux_entropy_disable );
+PROVIDE_ENTROPY ( linux, get_noise, linux_get_noise );
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_nap.c b/qemu/roms/ipxe/src/interface/linux/linux_nap.c
new file mode 100644
index 000000000..f1d3cd962
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_nap.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/nap.h>
+
+#include <linux_api.h>
+
+/** @file
+ *
+ * iPXE CPU sleeping API for linux
+ *
+ */
+
+/**
+ * Sleep until next CPU interrupt
+ *
+ */
+static void linux_cpu_nap(void)
+{
+ linux_usleep(0);
+}
+
+PROVIDE_NAP(linux, cpu_nap, linux_cpu_nap);
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_pci.c b/qemu/roms/ipxe/src/interface/linux/linux_pci.c
new file mode 100644
index 000000000..cbd825c18
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_pci.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <linux_api.h>
+#include <ipxe/linux.h>
+#include <ipxe/pci.h>
+
+/** @file
+ *
+ * iPXE PCI API for Linux
+ *
+ */
+
+/**
+ * Open PCI configuration space
+ *
+ * @v pci PCI device
+ * @v flags Access mode flags
+ * @v where Address within configuration space
+ * @ret fd File handle, or negative error
+ */
+static int linux_pci_open ( struct pci_device *pci, int flags,
+ unsigned long where ) {
+ char filename[ 22 /* "/proc/bus/pci/xx/xx.x" + NUL */ ];
+ int fd;
+ int rc;
+
+ /* Construct filename */
+ snprintf ( filename, sizeof ( filename ), "/proc/bus/pci/%02x/%02x.%x",
+ PCI_BUS ( pci->busdevfn ), PCI_SLOT ( pci->busdevfn ),
+ PCI_FUNC ( pci->busdevfn ) );
+
+ /* Open file */
+ fd = linux_open ( filename, flags );
+ if ( fd < 0 ) {
+ DBGC ( pci, "PCI could not open %s: %s\n", filename,
+ linux_strerror ( linux_errno ) );
+ rc = -ELINUX ( linux_errno );
+ goto err_open;
+ }
+
+ /* Seek to location */
+ if ( linux_lseek ( fd, where, SEEK_SET ) < 0 ) {
+ DBGC ( pci, "PCI could not seek to %s offset %#02lx: %s\n",
+ filename, where, linux_strerror ( linux_errno ) );
+ rc = -ELINUX ( linux_errno );
+ goto err_seek;
+ }
+
+ return fd;
+
+ err_seek:
+ linux_close ( fd );
+ err_open:
+ return rc;
+}
+
+/**
+ * Read from PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Address within configuration space
+ * @v value Data buffer
+ * @v len Length to read
+ * @ret rc Return status code
+ */
+int linux_pci_read ( struct pci_device *pci, unsigned long where,
+ unsigned long *value, size_t len ) {
+ uint32_t tmp = 0;
+ int fd;
+ int check_len;
+ int rc;
+
+ /* Return "missing device" in case of error */
+ *value = -1UL;
+
+ /* Open configuration space */
+ fd = linux_pci_open ( pci, O_RDONLY, where );
+ if ( fd < 0 ) {
+ rc = fd;
+ goto err_open;
+ }
+
+ /* Read value */
+ check_len = linux_read ( fd, &tmp, len );
+ if ( check_len < 0 ) {
+ DBGC ( pci, "PCI could not read from " PCI_FMT " %#02lx+%#zx: "
+ "%s\n", PCI_ARGS ( pci ), where, len,
+ linux_strerror ( linux_errno ) );
+ rc = -ELINUX ( linux_errno );
+ goto err_read;
+ }
+ if ( ( size_t ) check_len != len ) {
+ DBGC ( pci, "PCI read only %#x bytes from " PCI_FMT
+ " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ),
+ where, len );
+ rc = -EIO;
+ goto err_read;
+ }
+
+ /* Return value */
+ *value = le32_to_cpu ( tmp );
+
+ /* Success */
+ rc = 0;
+
+ err_read:
+ linux_close ( fd );
+ err_open:
+ return rc;
+}
+
+/**
+ * Write to PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Address within configuration space
+ * @v value Value to write
+ * @v len Length of value
+ * @ret rc Return status code
+ */
+int linux_pci_write ( struct pci_device *pci, unsigned long where,
+ unsigned long value, size_t len ) {
+ uint32_t tmp;
+ int fd;
+ int check_len;
+ int rc;
+
+ /* Open configuration space */
+ fd = linux_pci_open ( pci, O_WRONLY, where );
+ if ( fd < 0 ) {
+ rc = fd;
+ goto err_open;
+ }
+
+ /* Prepare value for writing */
+ tmp = cpu_to_le32 ( value );
+ assert ( len <= sizeof ( tmp ) );
+
+ /* Write value */
+ check_len = linux_write ( fd, &tmp, len );
+ if ( check_len < 0 ) {
+ DBGC ( pci, "PCI could not write to " PCI_FMT " %#02lx+%#zx: "
+ "%s\n", PCI_ARGS ( pci ), where, len,
+ linux_strerror ( linux_errno ) );
+ rc = -ELINUX ( linux_errno );
+ goto err_write;
+ }
+ if ( ( size_t ) check_len != len ) {
+ DBGC ( pci, "PCI wrote only %#x bytes to " PCI_FMT
+ " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ),
+ where, len );
+ rc = -EIO;
+ goto err_write;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_write:
+ linux_close ( fd );
+ err_open:
+ return rc;
+}
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_smbios.c b/qemu/roms/ipxe/src/interface/linux/linux_smbios.c
new file mode 100644
index 000000000..6e5174d23
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_smbios.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <linux_api.h>
+#include <ipxe/linux.h>
+#include <ipxe/smbios.h>
+
+/** SMBIOS filename */
+static const char smbios_filename[] = "/dev/mem";
+
+/** SMBIOS entry point scan region start address */
+#define SMBIOS_ENTRY_START 0xf0000
+
+/** SMBIOS entry point scan region length */
+#define SMBIOS_ENTRY_LEN 0x10000
+
+/** SMBIOS mapping alignment */
+#define SMBIOS_ALIGN 0x1000
+
+/**
+ * Find SMBIOS
+ *
+ * @v smbios SMBIOS entry point descriptor structure to fill in
+ * @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;
+ 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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 );
+
+ /* Unmap the entry point region (no longer required) */
+ linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN );
+
+ 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:
+ return rc;
+}
+
+PROVIDE_SMBIOS ( linux, find_smbios, linux_find_smbios );
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_time.c b/qemu/roms/ipxe/src/interface/linux/linux_time.c
new file mode 100644
index 000000000..e3cbafec6
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_time.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Linux time source
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <errno.h>
+#include <linux_api.h>
+#include <ipxe/time.h>
+
+/**
+ * Get current time in seconds
+ *
+ * @ret time Time, in seconds
+ */
+static time_t linux_now ( void ) {
+ struct timeval now;
+
+ linux_gettimeofday ( &now, NULL );
+ return now.tv_sec;
+}
+
+PROVIDE_TIME ( linux, time_now, linux_now );
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_timer.c b/qemu/roms/ipxe/src/interface/linux/linux_timer.c
new file mode 100644
index 000000000..7a994517b
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_timer.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <stddef.h>
+#include <ipxe/timer.h>
+
+#include <linux_api.h>
+
+/** @file
+ *
+ * iPXE timer API for linux
+ *
+ */
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static void linux_udelay(unsigned long usecs)
+{
+ linux_usleep(usecs);
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static unsigned long linux_ticks_per_sec(void)
+{
+ return 1000;
+}
+
+/**
+ * Get current system time in ticks
+ *
+ * linux doesn't provide an easy access to jiffies so implement it by measuring
+ * the time since the first call to this function.
+ *
+ * Since this function is used to seed the (non-cryptographic) random
+ * number generator, we round the start time down to the nearest whole
+ * second. This minimises the chances of generating identical RNG
+ * sequences (and hence identical TCP port numbers, etc) on
+ * consecutive invocations of iPXE.
+ *
+ * @ret ticks Current time, in ticks
+ */
+static unsigned long linux_currticks(void)
+{
+ static struct timeval start;
+ static int initialized = 0;
+
+ if (! initialized) {
+ linux_gettimeofday(&start, NULL);
+ initialized = 1;
+ }
+
+ struct timeval now;
+ linux_gettimeofday(&now, NULL);
+
+ unsigned long ticks = (now.tv_sec - start.tv_sec) * linux_ticks_per_sec();
+ ticks += now.tv_usec / (long)(1000000 / linux_ticks_per_sec());
+
+ return ticks;
+}
+
+PROVIDE_TIMER(linux, udelay, linux_udelay);
+PROVIDE_TIMER(linux, currticks, linux_currticks);
+PROVIDE_TIMER(linux, ticks_per_sec, linux_ticks_per_sec);
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_uaccess.c b/qemu/roms/ipxe/src/interface/linux/linux_uaccess.c
new file mode 100644
index 000000000..5ab0b6b65
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_uaccess.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <ipxe/uaccess.h>
+
+/** @file
+ *
+ * iPXE user access API for linux
+ *
+ */
+
+PROVIDE_UACCESS_INLINE(linux, phys_to_user);
+PROVIDE_UACCESS_INLINE(linux, user_to_phys);
+PROVIDE_UACCESS_INLINE(linux, virt_to_user);
+PROVIDE_UACCESS_INLINE(linux, user_to_virt);
+PROVIDE_UACCESS_INLINE(linux, userptr_add);
+PROVIDE_UACCESS_INLINE(linux, memcpy_user);
+PROVIDE_UACCESS_INLINE(linux, memmove_user);
+PROVIDE_UACCESS_INLINE(linux, memset_user);
+PROVIDE_UACCESS_INLINE(linux, strlen_user);
+PROVIDE_UACCESS_INLINE(linux, memchr_user);
diff --git a/qemu/roms/ipxe/src/interface/linux/linux_umalloc.c b/qemu/roms/ipxe/src/interface/linux/linux_umalloc.c
new file mode 100644
index 000000000..aa0052c53
--- /dev/null
+++ b/qemu/roms/ipxe/src/interface/linux/linux_umalloc.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+#include <valgrind/memcheck.h>
+
+/** @file
+ *
+ * iPXE user memory allocation API for linux
+ *
+ */
+
+#include <assert.h>
+#include <ipxe/umalloc.h>
+
+#include <linux_api.h>
+
+/** Special address returned for empty allocations */
+#define NOWHERE ((void *)-1)
+
+/** Poison to make the metadata more unique */
+#define POISON 0xa5a5a5a5
+#define min(a,b) (((a)<(b))?(a):(b))
+
+/** Metadata stored at the beginning of all allocations */
+struct metadata
+{
+ unsigned poison;
+ size_t size;
+};
+
+#define SIZE_MD (sizeof(struct metadata))
+
+/** Simple realloc which passes most of the work to mmap(), mremap() and munmap() */
+static void * linux_realloc(void *ptr, size_t size)
+{
+ struct metadata md = {0, 0};
+ struct metadata * mdptr = NULL;
+
+ DBG2("linux_realloc(%p, %zd)\n", ptr, size);
+
+ /* Check whether we have a valid pointer */
+ if (ptr != NULL && ptr != NOWHERE) {
+ mdptr = ptr - SIZE_MD;
+ VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD);
+ md = *mdptr;
+ VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD);
+
+ /* Check for poison in the metadata */
+ if (md.poison != POISON) {
+ DBG("linux_realloc bad poison: 0x%x (expected 0x%x)\n", md.poison, POISON);
+ return NULL;
+ }
+ } else {
+ /* Handle NOWHERE as NULL */
+ ptr = NULL;
+ }
+
+ /*
+ * At this point, ptr is either NULL or pointing to a region allocated by us.
+ * In the latter case mdptr is pointing to a valid metadata, otherwise it is NULL.
+ */
+
+ /* Handle deallocation or allocation of size 0 */
+ if (size == 0) {
+ if (mdptr) {
+ if (linux_munmap(mdptr, md.size))
+ DBG("linux_realloc munmap failed: %s\n", linux_strerror(linux_errno));
+ VALGRIND_FREELIKE_BLOCK(ptr, sizeof(*mdptr));
+ }
+ return NOWHERE;
+ }
+
+ if (ptr) {
+ char *vbits = NULL;
+
+ if (RUNNING_ON_VALGRIND > 0)
+ vbits = linux_realloc(NULL, min(size, md.size));
+
+/* prevent an unused variable warning when building w/o valgrind support */
+#ifndef NVALGRIND
+ VALGRIND_GET_VBITS(ptr, vbits, min(size, md.size));
+#endif
+
+ VALGRIND_FREELIKE_BLOCK(ptr, SIZE_MD);
+
+ mdptr = linux_mremap(mdptr, md.size + SIZE_MD, size + SIZE_MD, MREMAP_MAYMOVE);
+ if (mdptr == MAP_FAILED) {
+ DBG("linux_realloc mremap failed: %s\n", linux_strerror(linux_errno));
+ return NULL;
+ }
+ ptr = ((void *)mdptr) + SIZE_MD;
+
+ VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0);
+/* prevent an unused variable warning when building w/o valgrind support */
+#ifndef NVALGRIND
+ VALGRIND_SET_VBITS(ptr, vbits, min(size, md.size));
+#endif
+
+ if (RUNNING_ON_VALGRIND > 0)
+ linux_realloc(vbits, 0);
+ } else {
+ mdptr = linux_mmap(NULL, size + SIZE_MD, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (mdptr == MAP_FAILED) {
+ DBG("linux_realloc mmap failed: %s\n", linux_strerror(linux_errno));
+ return NULL;
+ }
+ ptr = ((void *)mdptr) + SIZE_MD;
+ VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0);
+ }
+
+ /* Update the metadata */
+ VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD);
+ mdptr->poison = POISON;
+ mdptr->size = size;
+ VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD);
+ // VALGRIND_MALLOCLIKE_BLOCK ignores redzones currently, make our own
+ VALGRIND_MAKE_MEM_NOACCESS(ptr + size, SIZE_MD);
+
+ return ptr;
+}
+
+/**
+ * Reallocate external memory
+ *
+ * @v old_ptr Memory previously allocated by umalloc(), or UNULL
+ * @v new_size Requested size
+ * @ret new_ptr Allocated memory, or UNULL
+ *
+ * Calling realloc() with a new size of zero is a valid way to free a
+ * memory block.
+ */
+static userptr_t linux_urealloc(userptr_t old_ptr, size_t new_size)
+{
+ return (userptr_t)linux_realloc((void *)old_ptr, new_size);
+}
+
+PROVIDE_UMALLOC(linux, urealloc, linux_urealloc);