[pxe] Split out platform-independent portions of cachedhcp.c

Split out the portions of cachedhcp.c that can be shared between BIOS
and UEFI (both of which can provide a buffer containing a previously
obtained DHCP packet, and neither of which provide a means to
determine the length of this DHCP packet).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
diff --git a/src/arch/x86/interface/pcbios/bios_cachedhcp.c b/src/arch/x86/interface/pcbios/bios_cachedhcp.c
new file mode 100644
index 0000000..3d38699
--- /dev/null
+++ b/src/arch/x86/interface/pcbios/bios_cachedhcp.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <ipxe/init.h>
+#include <ipxe/cachedhcp.h>
+#include <realmode.h>
+#include <pxe_api.h>
+
+/** @file
+ *
+ * Cached DHCP packet
+ *
+ */
+
+/** Cached DHCPACK physical address
+ *
+ * This can be set by the prefix.
+ */
+uint32_t __bss16 ( cached_dhcpack_phys );
+#define cached_dhcpack_phys __use_data16 ( cached_dhcpack_phys )
+
+/** Colour for debug messages */
+#define colour &cached_dhcpack_phys
+
+/**
+ * Cached DHCPACK initialisation function
+ *
+ */
+static void cachedhcp_init ( void ) {
+	int rc;
+
+	/* Do nothing if no cached DHCPACK is present */
+	if ( ! cached_dhcpack_phys ) {
+		DBGC ( colour, "CACHEDHCP found no cached DHCPACK\n" );
+		return;
+	}
+
+	/* Record cached DHCPACK */
+	if ( ( rc = cachedhcp_record ( phys_to_user ( cached_dhcpack_phys ),
+				       sizeof ( BOOTPLAYER_t ) ) ) != 0 ) {
+		DBGC ( colour, "CACHEDHCP could not record DHCPACK: %s\n",
+		       strerror ( rc ) );
+		return;
+	}
+
+	/* Mark as consumed */
+	cached_dhcpack_phys = 0;
+}
+
+/** Cached DHCPACK initialisation function */
+struct init_fn cachedhcp_init_fn __init_fn ( INIT_NORMAL ) = {
+	.initialise = cachedhcp_init,
+};
diff --git a/src/arch/x86/core/cachedhcp.c b/src/core/cachedhcp.c
similarity index 79%
rename from src/arch/x86/core/cachedhcp.c
rename to src/core/cachedhcp.c
index dffafe3..0e7da4b 100644
--- a/src/arch/x86/core/cachedhcp.c
+++ b/src/core/cachedhcp.c
@@ -25,11 +25,11 @@
 
 #include <stdint.h>
 #include <stdlib.h>
+#include <errno.h>
 #include <ipxe/dhcppkt.h>
 #include <ipxe/init.h>
 #include <ipxe/netdevice.h>
-#include <realmode.h>
-#include <pxe_api.h>
+#include <ipxe/cachedhcp.h>
 
 /** @file
  *
@@ -37,50 +37,33 @@
  *
  */
 
-/** Cached DHCPACK physical address
- *
- * This can be set by the prefix.
- */
-uint32_t __bss16 ( cached_dhcpack_phys );
-#define cached_dhcpack_phys __use_data16 ( cached_dhcpack_phys )
-
-/** Colour for debug messages */
-#define colour &cached_dhcpack_phys
-
 /** Cached DHCPACK */
 static struct dhcp_packet *cached_dhcpack;
 
+/** Colour for debug messages */
+#define colour &cached_dhcpack
+
 /**
- * Cached DHCPACK startup function
+ * Record cached DHCPACK
  *
+ * @v data		DHCPACK packet buffer
+ * @v max_len		Maximum possible length
+ * @ret rc		Return status code
  */
-static void cachedhcp_init ( void ) {
+int cachedhcp_record ( userptr_t data, size_t max_len ) {
 	struct dhcp_packet *dhcppkt;
 	struct dhcp_packet *tmp;
 	struct dhcphdr *dhcphdr;
-	size_t max_len;
 	size_t len;
 
-	/* Do nothing if no cached DHCPACK is present */
-	if ( ! cached_dhcpack_phys ) {
-		DBGC ( colour, "CACHEDHCP found no cached DHCPACK\n" );
-		return;
-	}
-
-	/* No reliable way to determine length before parsing packet;
-	 * start by assuming maximum length permitted by PXE.
-	 */
-	max_len = sizeof ( BOOTPLAYER_t );
-
 	/* Allocate and populate DHCP packet */
 	dhcppkt = zalloc ( sizeof ( *dhcppkt ) + max_len );
 	if ( ! dhcppkt ) {
 		DBGC ( colour, "CACHEDHCP could not allocate copy\n" );
-		return;
+		return -ENOMEM;
 	}
 	dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
-	copy_from_user ( dhcphdr, phys_to_user ( cached_dhcpack_phys ), 0,
-			 max_len );
+	copy_from_user ( dhcphdr, data, 0, max_len );
 	dhcppkt_init ( dhcppkt, dhcphdr, max_len );
 
 	/* Shrink packet to required length.  If reallocation fails,
@@ -98,10 +81,11 @@
 	dhcppkt_init ( dhcppkt, dhcphdr, len );
 
 	/* Store as cached DHCPACK, and mark original copy as consumed */
-	DBGC ( colour, "CACHEDHCP found cached DHCPACK at %08x+%zx\n",
-	       cached_dhcpack_phys, len );
+	DBGC ( colour, "CACHEDHCP found cached DHCPACK at %#08lx+%#zx/%#zx\n",
+	       user_to_phys ( data, 0 ), len, max_len );
 	cached_dhcpack = dhcppkt;
-	cached_dhcpack_phys = 0;
+
+	return 0;
 }
 
 /**
@@ -120,11 +104,6 @@
 	}
 }
 
-/** Cached DHCPACK initialisation function */
-struct init_fn cachedhcp_init_fn __init_fn ( INIT_NORMAL ) = {
-	.initialise = cachedhcp_init,
-};
-
 /** Cached DHCPACK startup function */
 struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
 	.name = "cachedhcp",
diff --git a/src/include/ipxe/cachedhcp.h b/src/include/ipxe/cachedhcp.h
new file mode 100644
index 0000000..7765c64
--- /dev/null
+++ b/src/include/ipxe/cachedhcp.h
@@ -0,0 +1,17 @@
+#ifndef _IPXE_CACHEDHCP_H
+#define _IPXE_CACHEDHCP_H
+
+/** @file
+ *
+ * Cached DHCP packet
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stddef.h>
+#include <ipxe/uaccess.h>
+
+extern int cachedhcp_record ( userptr_t data, size_t max_len );
+
+#endif /* _IPXE_CACHEDHCP_H */
diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h
index f14cb86..4c1c334 100644
--- a/src/include/ipxe/errfile.h
+++ b/src/include/ipxe/errfile.h
@@ -76,6 +76,7 @@
 #define ERRFILE_dummy_sanboot	       ( ERRFILE_CORE | 0x00240000 )
 #define ERRFILE_fdt		       ( ERRFILE_CORE | 0x00250000 )
 #define ERRFILE_dma		       ( ERRFILE_CORE | 0x00260000 )
+#define ERRFILE_cachedhcp	       ( ERRFILE_CORE | 0x00270000 )
 
 #define ERRFILE_eisa		     ( ERRFILE_DRIVER | 0x00000000 )
 #define ERRFILE_isa		     ( ERRFILE_DRIVER | 0x00010000 )