david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[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>
This commit is contained in:
Michael Brown 2012-09-04 01:26:48 +01:00
parent 03f0c23f8b
commit e6427b7ee1
6 changed files with 181 additions and 0 deletions

136
src/arch/i386/image/sdi.c Normal file
View File

@ -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,
};

View File

@ -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 */

View File

@ -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 )

View File

@ -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

View File

@ -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

View File

@ -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 */
/** @} */