summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/image
diff options
context:
space:
mode:
authorMichael Brown2005-05-24 01:05:45 +0200
committerMichael Brown2005-05-24 01:05:45 +0200
commit079b5d5527d7acde289d414c5102bdd9ddbe03ec (patch)
treeba2cf2f8c65ba10975ed60698dddd34a27c245d4 /src/arch/i386/image
parentMoved pxe_errors.c to pxe/interface/ (diff)
downloadipxe-079b5d5527d7acde289d414c5102bdd9ddbe03ec.tar.gz
ipxe-079b5d5527d7acde289d414c5102bdd9ddbe03ec.tar.xz
ipxe-079b5d5527d7acde289d414c5102bdd9ddbe03ec.zip
Moved pxe_loader.c to pxe_image.c to avoid name clash
Diffstat (limited to 'src/arch/i386/image')
-rw-r--r--src/arch/i386/image/pxe_image.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/arch/i386/image/pxe_image.c b/src/arch/i386/image/pxe_image.c
new file mode 100644
index 00000000..1b611891
--- /dev/null
+++ b/src/arch/i386/image/pxe_image.c
@@ -0,0 +1,94 @@
+/*
+ * PXE image loader for Etherboot.
+ *
+ * Note: There is no signature check for PXE images because there is
+ * no signature. Well done, Intel! Consequently, pxe_probe() must be
+ * called last of all the image_probe() routines, because it will
+ * *always* claim the image.
+ */
+
+#ifndef PXE_EXPORT
+#error PXE_IMAGE requires PXE_EXPORT
+#endif
+
+#include "etherboot.h"
+#include "pxe_callbacks.h"
+#include "pxe_export.h"
+#include "pxe.h"
+
+unsigned long pxe_load_offset;
+
+static sector_t pxe_download ( unsigned char *data,
+ unsigned int len, int eof );
+
+static inline os_download_t pxe_probe ( unsigned char *data __unused,
+ unsigned int len __unused ) {
+ printf("(PXE)");
+ pxe_load_offset = 0;
+ return pxe_download;
+}
+
+static sector_t pxe_download ( unsigned char *data,
+ unsigned int len, int eof ) {
+ unsigned long block_address = PXE_LOAD_ADDRESS + pxe_load_offset;
+ PXENV_STATUS_t nbp_exit;
+
+ /* Check segment will fit. We can't do this in probe()
+ * because there's nothing in the non-existent header to tell
+ * us how long the image is.
+ */
+ if ( ! prep_segment ( block_address, block_address + len,
+ block_address + len,
+ pxe_load_offset, pxe_load_offset + len ) ) {
+ longjmp ( restart_etherboot, -2 );
+ }
+
+ /* Load block into memory, continue loading until eof */
+ memcpy ( phys_to_virt ( block_address ), data, len );
+ pxe_load_offset += len;
+ if ( ! eof ) {
+ return 0;
+ }
+
+ /* Start up PXE NBP */
+ done ( 0 );
+
+ /* Install and activate a PXE stack */
+ pxe_stack = install_pxe_stack ( NULL );
+ if ( ensure_pxe_state ( READY ) ) {
+ /* Invoke the NBP */
+ nbp_exit = xstartpxe();
+ } else {
+ /* Fake success so we tear down the stack */
+ nbp_exit = PXENV_STATUS_SUCCESS;
+ }
+
+ /* NBP has three exit codes:
+ * PXENV_STATUS_KEEP_UNDI : keep UNDI and boot next device
+ * PXENV_STATUS_KEEP_ALL : keep all and boot next device
+ * anything else : remove all and boot next device
+ *
+ * Strictly, we're meant to hand back to the BIOS, but this
+ * would prevent the useful combination of "PXE NBP fails, so
+ * let Etherboot try to boot its next device". We therefore
+ * take liberties.
+ */
+ if ( nbp_exit != PXENV_STATUS_KEEP_UNDI &&
+ nbp_exit != PXENV_STATUS_KEEP_ALL ) {
+ /* Tear down PXE stack */
+ remove_pxe_stack();
+ }
+
+ /* Boot next device. Under strict PXE compliance, exit back
+ * to the BIOS, otherwise let Etherboot move to the next
+ * device.
+ */
+#ifdef PXE_STRICT
+ longjmp ( restart_etherboot, 255 );
+#else
+ longjmp ( restart_etherboot, 4 );
+#endif
+
+ /* Never reached; avoid compiler warning */
+ return ( 0 );
+}