Skip to content

Commit e6427b7

Browse files
committed
[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>
1 parent 03f0c23 commit e6427b7

File tree

6 files changed

+181
-0
lines changed

6 files changed

+181
-0
lines changed

src/arch/i386/image/sdi.c

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License as
6+
* published by the Free Software Foundation; either version 2 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17+
* 02110-1301, USA.
18+
*/
19+
20+
FILE_LICENCE ( GPL2_OR_LATER );
21+
22+
#include <stdint.h>
23+
#include <string.h>
24+
#include <errno.h>
25+
#include <realmode.h>
26+
#include <sdi.h>
27+
#include <ipxe/image.h>
28+
#include <ipxe/features.h>
29+
30+
/** @file
31+
*
32+
* System Deployment Image (SDI)
33+
*
34+
* Based on the MSDN article "RAM boot using SDI in Windows XP
35+
* Embedded with Service Pack 1", available at the time of writing
36+
* from:
37+
*
38+
* http://msdn.microsoft.com/en-us/library/ms838543.aspx
39+
*/
40+
41+
FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 );
42+
43+
/**
44+
* Parse SDI image header
45+
*
46+
* @v image SDI file
47+
* @v sdi SDI header to fill in
48+
* @ret rc Return status code
49+
*/
50+
static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) {
51+
52+
/* Sanity check */
53+
if ( image->len < sizeof ( *sdi ) ) {
54+
DBGC ( image, "SDI %p too short for SDI header\n", image );
55+
return -ENOEXEC;
56+
}
57+
58+
/* Read in header */
59+
copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) );
60+
61+
/* Check signature */
62+
if ( sdi->magic != SDI_MAGIC ) {
63+
DBGC ( image, "SDI %p is not an SDI image\n", image );
64+
return -ENOEXEC;
65+
}
66+
67+
return 0;
68+
}
69+
70+
/**
71+
* Execute SDI image
72+
*
73+
* @v image SDI file
74+
* @ret rc Return status code
75+
*/
76+
static int sdi_exec ( struct image *image ) {
77+
struct sdi_header sdi;
78+
uint32_t sdiptr;
79+
int rc;
80+
81+
/* Parse image header */
82+
if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
83+
return rc;
84+
85+
/* Check that image is bootable */
86+
if ( sdi.boot_size == 0 ) {
87+
DBGC ( image, "SDI %p is not bootable\n", image );
88+
return -ENOTTY;
89+
}
90+
DBGC ( image, "SDI %p image at %08lx+%08zx\n",
91+
image, user_to_phys ( image->data, 0 ), image->len );
92+
DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image,
93+
user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size );
94+
95+
/* Copy boot code */
96+
memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0,
97+
image->data, sdi.boot_offset, sdi.boot_size );
98+
99+
/* Jump to boot code */
100+
sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF );
101+
__asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" )
102+
: : "i" ( SDI_BOOT_SEG ),
103+
"i" ( SDI_BOOT_OFF ),
104+
"d" ( sdiptr ) );
105+
106+
/* There is no way for the image to return, since we provide
107+
* no return address.
108+
*/
109+
assert ( 0 );
110+
111+
return -ECANCELED; /* -EIMPOSSIBLE */
112+
}
113+
114+
/**
115+
* Probe SDI image
116+
*
117+
* @v image SDI file
118+
* @ret rc Return status code
119+
*/
120+
static int sdi_probe ( struct image *image ) {
121+
struct sdi_header sdi;
122+
int rc;
123+
124+
/* Parse image */
125+
if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
126+
return rc;
127+
128+
return 0;
129+
}
130+
131+
/** SDI image type */
132+
struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = {
133+
.name = "SDI",
134+
.probe = sdi_probe,
135+
.exec = sdi_exec,
136+
};

src/arch/i386/include/sdi.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef _SDI_H
2+
#define _SDI_H
3+
4+
/** @file
5+
*
6+
* System Deployment Image (SDI)
7+
*
8+
*/
9+
10+
FILE_LICENCE ( GPL2_OR_LATER );
11+
12+
/** SDI image header */
13+
struct sdi_header {
14+
/** Signature */
15+
uint32_t magic;
16+
/** Version (as an ASCII string) */
17+
uint32_t version;
18+
/** Reserved */
19+
uint8_t reserved[8];
20+
/** Boot code offset */
21+
uint64_t boot_offset;
22+
/** Boot code size */
23+
uint64_t boot_size;
24+
} __attribute__ (( packed ));
25+
26+
/** SDI image signature */
27+
#define SDI_MAGIC \
28+
( ( '$' << 0 ) | ( 'S' << 8 ) | ( 'D' << 16 ) | ( 'I' << 24 ) )
29+
30+
/** SDI boot segment */
31+
#define SDI_BOOT_SEG 0x0000
32+
33+
/** SDI boot offset */
34+
#define SDI_BOOT_OFF 0x7c00
35+
36+
/** Constant to binary-OR with physical address of SDI image */
37+
#define SDI_WTF 0x41
38+
39+
#endif /* _SDI_H */

src/arch/x86/include/bits/errfile.h

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
3131
#define ERRFILE_com32 ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00080000 )
3232
#define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 )
3333
#define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 )
34+
#define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 )
3435

3536
#define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
3637
#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )

src/config/config.c

+3
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ REQUIRE_OBJECT ( comboot_resolv );
181181
#ifdef IMAGE_EFI
182182
REQUIRE_OBJECT ( efi_image );
183183
#endif
184+
#ifdef IMAGE_SDI
185+
REQUIRE_OBJECT ( sdi );
186+
#endif
184187

185188
/*
186189
* Drag in all requested commands

src/config/general.h

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
100100
//#define IMAGE_BZIMAGE /* Linux bzImage image support */
101101
//#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
102102
//#define IMAGE_EFI /* EFI image support */
103+
//#define IMAGE_SDI /* SDI image support */
103104

104105
/*
105106
* Command-line commands to include

src/include/ipxe/features.h

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
5353
#define DHCP_EB_FEATURE_FCOE 0x25 /**< FCoE protocol */
5454
#define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */
5555
#define DHCP_EB_FEATURE_MENU 0x27 /**< Menu support */
56+
#define DHCP_EB_FEATURE_SDI 0x28 /**< SDI image support */
5657

5758
/** @} */
5859

0 commit comments

Comments
 (0)