mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-22 09:31:51 +00:00
[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:
parent
03f0c23f8b
commit
e6427b7ee1
136
src/arch/i386/image/sdi.c
Normal file
136
src/arch/i386/image/sdi.c
Normal 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,
|
||||
};
|
39
src/arch/i386/include/sdi.h
Normal file
39
src/arch/i386/include/sdi.h
Normal 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 */
|
@ -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 )
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user