diff options
author | Michael Brown <mcb30@ipxe.org> | 2012-09-04 01:26:48 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2012-09-05 14:11:01 +0100 |
commit | e6427b7ee117ea4af0812bb13b57999bccd8e058 (patch) | |
tree | d92dd9b3ec03b78b77919dc5cd364b95d3cede4d | |
parent | 03f0c23f8b1a60575f788dd1b9d4ea47debf2345 (diff) | |
download | ipxe-e6427b7ee117ea4af0812bb13b57999bccd8e058.tar.gz |
[sdi] Add support for SDI images
Add support (disabled by default) for booting .sdi images as used by
Windows XP Embedded.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/arch/i386/image/sdi.c | 136 | ||||
-rw-r--r-- | src/arch/i386/include/sdi.h | 39 | ||||
-rw-r--r-- | src/arch/x86/include/bits/errfile.h | 1 | ||||
-rw-r--r-- | src/config/config.c | 3 | ||||
-rw-r--r-- | src/config/general.h | 1 | ||||
-rw-r--r-- | src/include/ipxe/features.h | 1 |
6 files changed, 181 insertions, 0 deletions
diff --git a/src/arch/i386/image/sdi.c b/src/arch/i386/image/sdi.c new file mode 100644 index 000000000..df1c3a868 --- /dev/null +++ b/src/arch/i386/image/sdi.c @@ -0,0 +1,136 @@ +/* + * 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 ); + +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <realmode.h> +#include <sdi.h> +#include <ipxe/image.h> +#include <ipxe/features.h> + +/** @file + * + * System Deployment Image (SDI) + * + * Based on the MSDN article "RAM boot using SDI in Windows XP + * Embedded with Service Pack 1", available at the time of writing + * from: + * + * http://msdn.microsoft.com/en-us/library/ms838543.aspx + */ + +FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 ); + +/** + * Parse SDI image header + * + * @v image SDI file + * @v sdi SDI header to fill in + * @ret rc Return status code + */ +static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) { + + /* Sanity check */ + if ( image->len < sizeof ( *sdi ) ) { + DBGC ( image, "SDI %p too short for SDI header\n", image ); + return -ENOEXEC; + } + + /* Read in header */ + copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) ); + + /* Check signature */ + if ( sdi->magic != SDI_MAGIC ) { + DBGC ( image, "SDI %p is not an SDI image\n", image ); + return -ENOEXEC; + } + + return 0; +} + +/** + * Execute SDI image + * + * @v image SDI file + * @ret rc Return status code + */ +static int sdi_exec ( struct image *image ) { + struct sdi_header sdi; + uint32_t sdiptr; + int rc; + + /* Parse image header */ + if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 ) + return rc; + + /* Check that image is bootable */ + if ( sdi.boot_size == 0 ) { + DBGC ( image, "SDI %p is not bootable\n", image ); + return -ENOTTY; + } + DBGC ( image, "SDI %p image at %08lx+%08zx\n", + image, user_to_phys ( image->data, 0 ), image->len ); + DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image, + user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size ); + + /* Copy boot code */ + memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0, + image->data, sdi.boot_offset, sdi.boot_size ); + + /* Jump to boot code */ + sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF ); + __asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" ) + : : "i" ( SDI_BOOT_SEG ), + "i" ( SDI_BOOT_OFF ), + "d" ( sdiptr ) ); + + /* There is no way for the image to return, since we provide + * no return address. + */ + assert ( 0 ); + + return -ECANCELED; /* -EIMPOSSIBLE */ +} + +/** + * Probe SDI image + * + * @v image SDI file + * @ret rc Return status code + */ +static int sdi_probe ( struct image *image ) { + struct sdi_header sdi; + int rc; + + /* Parse image */ + if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 ) + return rc; + + return 0; +} + +/** SDI image type */ +struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = { + .name = "SDI", + .probe = sdi_probe, + .exec = sdi_exec, +}; diff --git a/src/arch/i386/include/sdi.h b/src/arch/i386/include/sdi.h new file mode 100644 index 000000000..fc486402d --- /dev/null +++ b/src/arch/i386/include/sdi.h @@ -0,0 +1,39 @@ +#ifndef _SDI_H +#define _SDI_H + +/** @file + * + * System Deployment Image (SDI) + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** SDI image header */ +struct sdi_header { + /** Signature */ + uint32_t magic; + /** Version (as an ASCII string) */ + uint32_t version; + /** Reserved */ + uint8_t reserved[8]; + /** Boot code offset */ + uint64_t boot_offset; + /** Boot code size */ + uint64_t boot_size; +} __attribute__ (( packed )); + +/** SDI image signature */ +#define SDI_MAGIC \ + ( ( '$' << 0 ) | ( 'S' << 8 ) | ( 'D' << 16 ) | ( 'I' << 24 ) ) + +/** SDI boot segment */ +#define SDI_BOOT_SEG 0x0000 + +/** SDI boot offset */ +#define SDI_BOOT_OFF 0x7c00 + +/** Constant to binary-OR with physical address of SDI image */ +#define SDI_WTF 0x41 + +#endif /* _SDI_H */ diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index f66cbaa1a..25e070e8e 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_com32 ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00080000 ) #define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 ) #define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 ) +#define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 ) #define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 ) #define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 ) diff --git a/src/config/config.c b/src/config/config.c index 202da7266..78ae93c43 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -181,6 +181,9 @@ REQUIRE_OBJECT ( comboot_resolv ); #ifdef IMAGE_EFI REQUIRE_OBJECT ( efi_image ); #endif +#ifdef IMAGE_SDI +REQUIRE_OBJECT ( sdi ); +#endif /* * Drag in all requested commands diff --git a/src/config/general.h b/src/config/general.h index 6fc39831f..638320a46 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -100,6 +100,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); //#define IMAGE_BZIMAGE /* Linux bzImage image support */ //#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */ //#define IMAGE_EFI /* EFI image support */ +//#define IMAGE_SDI /* SDI image support */ /* * Command-line commands to include diff --git a/src/include/ipxe/features.h b/src/include/ipxe/features.h index 498ec9441..0c92f5be9 100644 --- a/src/include/ipxe/features.h +++ b/src/include/ipxe/features.h @@ -53,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define DHCP_EB_FEATURE_FCOE 0x25 /**< FCoE protocol */ #define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */ #define DHCP_EB_FEATURE_MENU 0x27 /**< Menu support */ +#define DHCP_EB_FEATURE_SDI 0x28 /**< SDI image support */ /** @} */ |