summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/acpi.c35
-rw-r--r--src/core/blocktrans.c4
-rw-r--r--src/core/cachedhcp.c158
-rw-r--r--src/core/dma.c179
-rw-r--r--src/core/image.c68
-rw-r--r--src/core/interface.c22
-rw-r--r--src/core/iobuf.c57
-rw-r--r--src/core/malloc.c4
-rw-r--r--src/core/null_acpi.c2
9 files changed, 497 insertions, 32 deletions
diff --git a/src/core/acpi.c b/src/core/acpi.c
index e6912afa2..52eb63a04 100644
--- a/src/core/acpi.c
+++ b/src/core/acpi.c
@@ -35,6 +35,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
+/** Colour for debug messages */
+#define colour FADT_SIGNATURE
+
/******************************************************************************
*
* Utility functions
@@ -80,13 +83,13 @@ void acpi_fix_checksum ( struct acpi_header *acpi ) {
}
/**
- * Locate ACPI table
+ * Locate ACPI table via RSDT
*
* @v signature Requested table signature
* @v index Requested index of table with this signature
* @ret table Table, or UNULL if not found
*/
-userptr_t acpi_find ( uint32_t signature, unsigned int index ) {
+userptr_t acpi_find_via_rsdt ( uint32_t signature, unsigned int index ) {
struct acpi_header acpi;
struct acpi_rsdt *rsdtab;
typeof ( rsdtab->entry[0] ) entry;
@@ -106,17 +109,17 @@ userptr_t acpi_find ( uint32_t signature, unsigned int index ) {
/* Read RSDT header */
copy_from_user ( &acpi, rsdt, 0, sizeof ( acpi ) );
if ( acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
- DBGC ( rsdt, "RSDT %#08lx has invalid signature:\n",
+ DBGC ( colour, "RSDT %#08lx has invalid signature:\n",
user_to_phys ( rsdt, 0 ) );
- DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
+ DBGC_HDA ( colour, user_to_phys ( rsdt, 0 ), &acpi,
sizeof ( acpi ) );
return UNULL;
}
len = le32_to_cpu ( acpi.length );
if ( len < sizeof ( rsdtab->acpi ) ) {
- DBGC ( rsdt, "RSDT %#08lx has invalid length:\n",
+ DBGC ( colour, "RSDT %#08lx has invalid length:\n",
user_to_phys ( rsdt, 0 ) );
- DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
+ DBGC_HDA ( colour, user_to_phys ( rsdt, 0 ), &acpi,
sizeof ( acpi ) );
return UNULL;
}
@@ -147,20 +150,20 @@ userptr_t acpi_find ( uint32_t signature, unsigned int index ) {
/* Check table integrity */
if ( acpi_checksum ( table ) != 0 ) {
- DBGC ( rsdt, "RSDT %#08lx found %s with bad checksum "
- "at %08lx\n", user_to_phys ( rsdt, 0 ),
+ DBGC ( colour, "RSDT %#08lx found %s with bad "
+ "checksum at %08lx\n", user_to_phys ( rsdt, 0 ),
acpi_name ( signature ),
user_to_phys ( table, 0 ) );
break;
}
- DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
+ DBGC ( colour, "RSDT %#08lx found %s at %08lx\n",
user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
user_to_phys ( table, 0 ) );
return table;
}
- DBGC ( rsdt, "RSDT %#08lx could not find %s\n",
+ DBGC ( colour, "RSDT %#08lx could not find %s\n",
user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
return UNULL;
}
@@ -256,20 +259,12 @@ static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
*/
int acpi_sx ( uint32_t signature ) {
struct acpi_fadt fadtab;
- userptr_t rsdt;
userptr_t fadt;
userptr_t dsdt;
userptr_t ssdt;
unsigned int i;
int sx;
- /* Locate RSDT */
- rsdt = acpi_find_rsdt();
- if ( ! rsdt ) {
- DBG ( "RSDT not found\n" );
- return -ENOENT;
- }
-
/* Try DSDT first */
fadt = acpi_find ( FADT_SIGNATURE, 0 );
if ( fadt ) {
@@ -288,8 +283,8 @@ int acpi_sx ( uint32_t signature ) {
return sx;
}
- DBGC ( rsdt, "RSDT %#08lx could not find \\_Sx \"%s\"\n",
- user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
+ DBGC ( colour, "ACPI could not find \\_Sx \"%s\"\n",
+ acpi_name ( signature ) );
return -ENOENT;
}
diff --git a/src/core/blocktrans.c b/src/core/blocktrans.c
index 3f32f9cf8..f9dcb95d2 100644
--- a/src/core/blocktrans.c
+++ b/src/core/blocktrans.c
@@ -242,9 +242,7 @@ int block_translate ( struct interface *block, userptr_t buffer, size_t size ) {
}
/* Attach to interfaces, mortalise self, and return */
- assert ( block->dest != &null_intf );
- intf_plug_plug ( &blktrans->xfer, block->dest );
- intf_plug_plug ( &blktrans->block, block );
+ intf_insert ( block, &blktrans->block, &blktrans->xfer );
ref_put ( &blktrans->refcnt );
DBGC2 ( blktrans, "BLKTRANS %p created", blktrans );
diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c
new file mode 100644
index 000000000..0e7da4bf2
--- /dev/null
+++ b/src/core/cachedhcp.c
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ipxe/dhcppkt.h>
+#include <ipxe/init.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/cachedhcp.h>
+
+/** @file
+ *
+ * Cached DHCP packet
+ *
+ */
+
+/** Cached DHCPACK */
+static struct dhcp_packet *cached_dhcpack;
+
+/** Colour for debug messages */
+#define colour &cached_dhcpack
+
+/**
+ * Record cached DHCPACK
+ *
+ * @v data DHCPACK packet buffer
+ * @v max_len Maximum possible length
+ * @ret rc Return status code
+ */
+int cachedhcp_record ( userptr_t data, size_t max_len ) {
+ struct dhcp_packet *dhcppkt;
+ struct dhcp_packet *tmp;
+ struct dhcphdr *dhcphdr;
+ size_t len;
+
+ /* Allocate and populate DHCP packet */
+ dhcppkt = zalloc ( sizeof ( *dhcppkt ) + max_len );
+ if ( ! dhcppkt ) {
+ DBGC ( colour, "CACHEDHCP could not allocate copy\n" );
+ return -ENOMEM;
+ }
+ dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
+ copy_from_user ( dhcphdr, data, 0, max_len );
+ dhcppkt_init ( dhcppkt, dhcphdr, max_len );
+
+ /* Shrink packet to required length. If reallocation fails,
+ * just continue to use the original packet and waste the
+ * unused space.
+ */
+ len = dhcppkt_len ( dhcppkt );
+ assert ( len <= max_len );
+ tmp = realloc ( dhcppkt, ( sizeof ( *dhcppkt ) + len ) );
+ if ( tmp )
+ dhcppkt = tmp;
+
+ /* Reinitialise packet at new address */
+ dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
+ dhcppkt_init ( dhcppkt, dhcphdr, len );
+
+ /* Store as cached DHCPACK, and mark original copy as consumed */
+ DBGC ( colour, "CACHEDHCP found cached DHCPACK at %#08lx+%#zx/%#zx\n",
+ user_to_phys ( data, 0 ), len, max_len );
+ cached_dhcpack = dhcppkt;
+
+ return 0;
+}
+
+/**
+ * Cached DHCPACK startup function
+ *
+ */
+static void cachedhcp_startup ( void ) {
+
+ /* If cached DHCP packet was not claimed by any network device
+ * during startup, then free it.
+ */
+ if ( cached_dhcpack ) {
+ DBGC ( colour, "CACHEDHCP freeing unclaimed cached DHCPACK\n" );
+ dhcppkt_put ( cached_dhcpack );
+ cached_dhcpack = NULL;
+ }
+}
+
+/** Cached DHCPACK startup function */
+struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
+ .name = "cachedhcp",
+ .startup = cachedhcp_startup,
+};
+
+/**
+ * Apply cached DHCPACK to network device, if applicable
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int cachedhcp_probe ( struct net_device *netdev ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ int rc;
+
+ /* Do nothing unless we have a cached DHCPACK */
+ if ( ! cached_dhcpack )
+ return 0;
+
+ /* Do nothing unless cached DHCPACK's MAC address matches this
+ * network device.
+ */
+ if ( memcmp ( netdev->ll_addr, cached_dhcpack->dhcphdr->chaddr,
+ ll_protocol->ll_addr_len ) != 0 ) {
+ DBGC ( colour, "CACHEDHCP cached DHCPACK does not match %s\n",
+ netdev->name );
+ return 0;
+ }
+ DBGC ( colour, "CACHEDHCP cached DHCPACK is for %s\n", netdev->name );
+
+ /* Register as DHCP settings for this network device */
+ if ( ( rc = register_settings ( &cached_dhcpack->settings,
+ netdev_settings ( netdev ),
+ DHCP_SETTINGS_NAME ) ) != 0 ) {
+ DBGC ( colour, "CACHEDHCP could not register settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Claim cached DHCPACK */
+ dhcppkt_put ( cached_dhcpack );
+ cached_dhcpack = NULL;
+
+ return 0;
+}
+
+/** Cached DHCP packet network device driver */
+struct net_driver cachedhcp_driver __net_driver = {
+ .name = "cachedhcp",
+ .probe = cachedhcp_probe,
+};
diff --git a/src/core/dma.c b/src/core/dma.c
new file mode 100644
index 000000000..5d6868216
--- /dev/null
+++ b/src/core/dma.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2020 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.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <assert.h>
+#include <errno.h>
+#include <ipxe/dma.h>
+
+/** @file
+ *
+ * DMA mappings
+ *
+ */
+
+/******************************************************************************
+ *
+ * Flat address space DMA API
+ *
+ ******************************************************************************
+ */
+
+PROVIDE_DMAAPI_INLINE ( flat, dma_map );
+PROVIDE_DMAAPI_INLINE ( flat, dma_unmap );
+PROVIDE_DMAAPI_INLINE ( flat, dma_alloc );
+PROVIDE_DMAAPI_INLINE ( flat, dma_free );
+PROVIDE_DMAAPI_INLINE ( flat, dma_umalloc );
+PROVIDE_DMAAPI_INLINE ( flat, dma_ufree );
+PROVIDE_DMAAPI_INLINE ( flat, dma_set_mask );
+PROVIDE_DMAAPI_INLINE ( flat, dma_phys );
+
+/******************************************************************************
+ *
+ * Operations-based DMA API
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Map buffer for DMA
+ *
+ * @v dma DMA device
+ * @v map DMA mapping to fill in
+ * @v addr Buffer address
+ * @v len Length of buffer
+ * @v flags Mapping flags
+ * @ret rc Return status code
+ */
+static int dma_op_map ( struct dma_device *dma, struct dma_mapping *map,
+ physaddr_t addr, size_t len, int flags ) {
+ struct dma_operations *op = dma->op;
+
+ if ( ! op )
+ return -ENODEV;
+ return op->map ( dma, map, addr, len, flags );
+}
+
+/**
+ * Unmap buffer
+ *
+ * @v map DMA mapping
+ */
+static void dma_op_unmap ( struct dma_mapping *map ) {
+ struct dma_device *dma = map->dma;
+
+ assert ( dma != NULL );
+ assert ( dma->op != NULL );
+ dma->op->unmap ( dma, map );
+}
+
+/**
+ * Allocate and map DMA-coherent buffer
+ *
+ * @v dma DMA device
+ * @v map DMA mapping to fill in
+ * @v len Length of buffer
+ * @v align Physical alignment
+ * @ret addr Buffer address, or NULL on error
+ */
+static void * dma_op_alloc ( struct dma_device *dma, struct dma_mapping *map,
+ size_t len, size_t align ) {
+ struct dma_operations *op = dma->op;
+
+ if ( ! op )
+ return NULL;
+ return op->alloc ( dma, map, len, align );
+}
+
+/**
+ * Unmap and free DMA-coherent buffer
+ *
+ * @v map DMA mapping
+ * @v addr Buffer address
+ * @v len Length of buffer
+ */
+static void dma_op_free ( struct dma_mapping *map, void *addr, size_t len ) {
+ struct dma_device *dma = map->dma;
+
+ assert ( dma != NULL );
+ assert ( dma->op != NULL );
+ dma->op->free ( dma, map, addr, len );
+}
+
+/**
+ * Allocate and map DMA-coherent buffer from external (user) memory
+ *
+ * @v dma DMA device
+ * @v map DMA mapping to fill in
+ * @v len Length of buffer
+ * @v align Physical alignment
+ * @ret addr Buffer address, or NULL on error
+ */
+static userptr_t dma_op_umalloc ( struct dma_device *dma,
+ struct dma_mapping *map,
+ size_t len, size_t align ) {
+ struct dma_operations *op = dma->op;
+
+ if ( ! op )
+ return UNULL;
+ return op->umalloc ( dma, map, len, align );
+}
+
+/**
+ * Unmap and free DMA-coherent buffer from external (user) memory
+ *
+ * @v map DMA mapping
+ * @v addr Buffer address
+ * @v len Length of buffer
+ */
+static void dma_op_ufree ( struct dma_mapping *map, userptr_t addr,
+ size_t len ) {
+ struct dma_device *dma = map->dma;
+
+ assert ( dma != NULL );
+ assert ( dma->op != NULL );
+ dma->op->ufree ( dma, map, addr, len );
+}
+
+/**
+ * Set addressable space mask
+ *
+ * @v dma DMA device
+ * @v mask Addressable space mask
+ */
+static void dma_op_set_mask ( struct dma_device *dma, physaddr_t mask ) {
+ struct dma_operations *op = dma->op;
+
+ if ( op )
+ op->set_mask ( dma, mask );
+}
+
+PROVIDE_DMAAPI ( op, dma_map, dma_op_map );
+PROVIDE_DMAAPI ( op, dma_unmap, dma_op_unmap );
+PROVIDE_DMAAPI ( op, dma_alloc, dma_op_alloc );
+PROVIDE_DMAAPI ( op, dma_free, dma_op_free );
+PROVIDE_DMAAPI ( op, dma_umalloc, dma_op_umalloc );
+PROVIDE_DMAAPI ( op, dma_ufree, dma_op_ufree );
+PROVIDE_DMAAPI ( op, dma_set_mask, dma_op_set_mask );
+PROVIDE_DMAAPI_INLINE ( op, dma_phys );
diff --git a/src/core/image.c b/src/core/image.c
index 078ce1bb9..9fe77c54c 100644
--- a/src/core/image.c
+++ b/src/core/image.c
@@ -176,6 +176,30 @@ int image_set_cmdline ( struct image *image, const char *cmdline ) {
}
/**
+ * Set image data
+ *
+ * @v image Image
+ * @v data Image data
+ * @v len Length of image data
+ * @ret rc Return status code
+ */
+int image_set_data ( struct image *image, userptr_t data, size_t len ) {
+ userptr_t new;
+
+ /* (Re)allocate image data */
+ new = urealloc ( image->data, len );
+ if ( ! new )
+ return -ENOMEM;
+ image->data = new;
+
+ /* Copy in new image data */
+ memcpy_user ( image->data, 0, data, 0, len );
+ image->len = len;
+
+ return 0;
+}
+
+/**
* Determine image type
*
* @v image Executable image
@@ -481,3 +505,47 @@ int image_set_trust ( int require_trusted, int permanent ) {
return 0;
}
+
+/**
+ * Create registered image from block of memory
+ *
+ * @v name Name
+ * @v data Image data
+ * @v len Length
+ * @ret image Image, or NULL on error
+ */
+struct image * image_memory ( const char *name, userptr_t data, size_t len ) {
+ struct image *image;
+ int rc;
+
+ /* Allocate image */
+ image = alloc_image ( NULL );
+ if ( ! image ) {
+ rc = -ENOMEM;
+ goto err_alloc_image;
+ }
+
+ /* Set name */
+ if ( ( rc = image_set_name ( image, name ) ) != 0 )
+ goto err_set_name;
+
+ /* Set data */
+ if ( ( rc = image_set_data ( image, data, len ) ) != 0 )
+ goto err_set_data;
+
+ /* Register image */
+ if ( ( rc = register_image ( image ) ) != 0 )
+ goto err_register;
+
+ /* Drop local reference to image */
+ image_put ( image );
+
+ return image;
+
+ err_register:
+ err_set_data:
+ err_set_name:
+ image_put ( image );
+ err_alloc_image:
+ return NULL;
+}
diff --git a/src/core/interface.c b/src/core/interface.c
index 402aa4541..34a4180a5 100644
--- a/src/core/interface.c
+++ b/src/core/interface.c
@@ -81,9 +81,14 @@ struct interface null_intf = INTF_INIT ( null_intf_desc );
* interface is updated to point to the new destination interface.
*/
void intf_plug ( struct interface *intf, struct interface *dest ) {
+
+ if ( intf == &null_intf )
+ return;
+
DBGC ( INTF_COL ( intf ),
"INTF " INTF_INTF_FMT " replug to " INTF_FMT "\n",
INTF_INTF_DBG ( intf, intf->dest ), INTF_DBG ( dest ) );
+
intf_get ( dest );
intf_put ( intf->dest );
intf->dest = dest;
@@ -386,6 +391,23 @@ void intfs_restart ( int rc, ... ) {
}
/**
+ * Insert a filter interface
+ *
+ * @v intf Object interface
+ * @v upper Upper end of filter
+ * @v lower Lower end of filter
+ */
+void intf_insert ( struct interface *intf, struct interface *upper,
+ struct interface *lower ) {
+ struct interface *dest = intf->dest;
+
+ intf_get ( dest );
+ intf_plug_plug ( intf, upper );
+ intf_plug_plug ( lower, dest );
+ intf_put ( dest );
+}
+
+/**
* Poke an object interface
*
* @v intf Object interface
diff --git a/src/core/iobuf.c b/src/core/iobuf.c
index 0ee53e038..c9970bc76 100644
--- a/src/core/iobuf.c
+++ b/src/core/iobuf.c
@@ -88,8 +88,8 @@ struct io_buffer * alloc_iob_raw ( size_t len, size_t align, size_t offset ) {
len += ( ( - len - offset ) & ( __alignof__ ( *iobuf ) - 1 ) );
/* Allocate memory for buffer plus descriptor */
- data = malloc_dma_offset ( len + sizeof ( *iobuf ), align,
- offset );
+ data = malloc_phys_offset ( len + sizeof ( *iobuf ), align,
+ offset );
if ( ! data )
return NULL;
iobuf = ( data + len );
@@ -97,19 +97,20 @@ struct io_buffer * alloc_iob_raw ( size_t len, size_t align, size_t offset ) {
} else {
/* Allocate memory for buffer */
- data = malloc_dma_offset ( len, align, offset );
+ data = malloc_phys_offset ( len, align, offset );
if ( ! data )
return NULL;
/* Allocate memory for descriptor */
iobuf = malloc ( sizeof ( *iobuf ) );
if ( ! iobuf ) {
- free_dma ( data, len );
+ free_phys ( data, len );
return NULL;
}
}
/* Populate descriptor */
+ memset ( &iobuf->map, 0, sizeof ( iobuf->map ) );
iobuf->head = iobuf->data = iobuf->tail = data;
iobuf->end = ( data + len );
@@ -153,23 +154,67 @@ void free_iob ( struct io_buffer *iobuf ) {
assert ( iobuf->head <= iobuf->data );
assert ( iobuf->data <= iobuf->tail );
assert ( iobuf->tail <= iobuf->end );
+ assert ( ! dma_mapped ( &iobuf->map ) );
/* Free buffer */
len = ( iobuf->end - iobuf->head );
if ( iobuf->end == iobuf ) {
/* Descriptor is inline */
- free_dma ( iobuf->head, ( len + sizeof ( *iobuf ) ) );
+ free_phys ( iobuf->head, ( len + sizeof ( *iobuf ) ) );
} else {
/* Descriptor is detached */
- free_dma ( iobuf->head, len );
+ free_phys ( iobuf->head, len );
free ( iobuf );
}
}
/**
+ * Allocate and map I/O buffer for receive DMA
+ *
+ * @v len Length of I/O buffer
+ * @v dma DMA device
+ * @ret iobuf I/O buffer, or NULL on error
+ */
+struct io_buffer * alloc_rx_iob ( size_t len, struct dma_device *dma ) {
+ struct io_buffer *iobuf;
+ int rc;
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( len );
+ if ( ! iobuf )
+ goto err_alloc;
+
+ /* Map I/O buffer */
+ if ( ( rc = iob_map_rx ( iobuf, dma ) ) != 0 )
+ goto err_map;
+
+ return iobuf;
+
+ iob_unmap ( iobuf );
+ err_map:
+ free_iob ( iobuf );
+ err_alloc:
+ return NULL;
+}
+
+/**
+ * Unmap and free I/O buffer for receive DMA
+ *
+ * @v iobuf I/O buffer
+ */
+void free_rx_iob ( struct io_buffer *iobuf ) {
+
+ /* Unmap I/O buffer */
+ iob_unmap ( iobuf );
+
+ /* Free I/O buffer */
+ free_iob ( iobuf );
+}
+
+/**
* Ensure I/O buffer has sufficient headroom
*
* @v iobuf I/O buffer
diff --git a/src/core/malloc.c b/src/core/malloc.c
index 0a7843a14..8499ab45a 100644
--- a/src/core/malloc.c
+++ b/src/core/malloc.c
@@ -596,8 +596,8 @@ void * malloc ( size_t size ) {
*
* @v ptr Memory allocated by malloc(), or NULL
*
- * Memory allocated with malloc_dma() cannot be freed with free(); it
- * must be freed with free_dma() instead.
+ * Memory allocated with malloc_phys() cannot be freed with free(); it
+ * must be freed with free_phys() instead.
*
* If @c ptr is NULL, no action is taken.
*/
diff --git a/src/core/null_acpi.c b/src/core/null_acpi.c
index 90c784855..acca37872 100644
--- a/src/core/null_acpi.c
+++ b/src/core/null_acpi.c
@@ -1,3 +1,3 @@
#include <ipxe/acpi.h>
-PROVIDE_ACPI_INLINE ( null, acpi_find_rsdt );
+PROVIDE_ACPI_INLINE ( null, acpi_find );