Skip to content

Commit

Permalink
[sdi] Add support for SDI images
Browse files Browse the repository at this point in the history
Add support (disabled by default) for booting .sdi images as used by
Windows XP Embedded.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Sep 5, 2012
1 parent 03f0c23 commit e6427b7
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 0 deletions.
136 changes: 136 additions & 0 deletions src/arch/i386/image/sdi.c
Original file line number Diff line number Diff line change
@@ -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,
};
39 changes: 39 additions & 0 deletions src/arch/i386/include/sdi.h
Original file line number Diff line number Diff line change
@@ -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 */
1 change: 1 addition & 0 deletions src/arch/x86/include/bits/errfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down
3 changes: 3 additions & 0 deletions src/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/config/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/include/ipxe/features.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

/** @} */

Expand Down

0 comments on commit e6427b7

Please sign in to comment.