iPXE
sdi.c
Go to the documentation of this file.
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 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stdint.h>
27#include <string.h>
28#include <errno.h>
29#include <realmode.h>
30#include <sdi.h>
31#include <ipxe/image.h>
32#include <ipxe/features.h>
33
34/** @file
35 *
36 * System Deployment Image (SDI)
37 *
38 * Based on the MSDN article "RAM boot using SDI in Windows XP
39 * Embedded with Service Pack 1", available at the time of writing
40 * from:
41 *
42 * http://msdn.microsoft.com/en-us/library/ms838543.aspx
43 */
44
46
47/**
48 * Execute SDI image
49 *
50 * @v image SDI file
51 * @ret rc Return status code
52 */
53static int sdi_exec ( struct image *image ) {
54 const struct sdi_header *sdi;
55 uint32_t sdiptr;
56
57 /* Sanity check */
58 assert ( image->len >= sizeof ( *sdi ) );
59 sdi = image->data;
60
61 /* Check that image is bootable */
62 if ( sdi->boot_size == 0 ) {
63 DBGC ( image, "SDI %s is not bootable\n", image->name );
64 return -ENOTTY;
65 }
66 DBGC ( image, "SDI %s image at %08lx+%08zx\n",
67 image->name, virt_to_phys ( image->data ), image->len );
68 DBGC ( image, "SDI %s boot code at %08llx+%llx\n", image->name,
69 ( virt_to_phys ( image->data ) + sdi->boot_offset ),
70 sdi->boot_size );
71
72 /* Copy boot code */
74 ( image->data + sdi->boot_offset ), sdi->boot_size );
75
76 /* Jump to boot code */
77 sdiptr = ( virt_to_phys ( image->data ) | SDI_WTF );
78 __asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" )
79 : : "i" ( SDI_BOOT_SEG ),
80 "i" ( SDI_BOOT_OFF ),
81 "d" ( sdiptr ) );
82
83 /* There is no way for the image to return, since we provide
84 * no return address.
85 */
86 assert ( 0 );
87
88 return -ECANCELED; /* -EIMPOSSIBLE */
89}
90
91/**
92 * Probe SDI image
93 *
94 * @v image SDI file
95 * @ret rc Return status code
96 */
97static int sdi_probe ( struct image *image ) {
98 const struct sdi_header *sdi;
99
100 /* Sanity check */
101 if ( image->len < sizeof ( *sdi ) ) {
102 DBGC ( image, "SDI %s too short for SDI header\n",
103 image->name );
104 return -ENOEXEC;
105 }
106 sdi = image->data;
107
108 /* Check signature */
109 if ( sdi->magic != SDI_MAGIC ) {
110 DBGC ( image, "SDI %s is not an SDI image\n",
111 image->name );
112 return -ENOEXEC;
113 }
114
115 return 0;
116}
117
118/** SDI image type */
119struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = {
120 .name = "SDI",
121 .probe = sdi_probe,
122 .exec = sdi_exec,
123};
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned int uint32_t
Definition stdint.h:12
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define DHCP_EB_FEATURE_SDI
SDI image support.
Definition features.h:57
#define FEATURE_IMAGE
Image formats.
Definition features.h:23
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOEXEC
Exec format error.
Definition errno.h:520
#define ECANCELED
Operation canceled.
Definition errno.h:344
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
Executable images.
#define PROBE_NORMAL
Normal image probe priority.
Definition image.h:156
#define __image_type(probe_order)
An executable image type.
Definition image.h:170
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
Feature list.
#define FEATURE(category, text, feature_opt, version)
Declare a feature.
Definition features.h:101
#define REAL_CODE(asm_code_str)
Definition libkir.h:226
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition realmode.h:77
static int sdi_probe(struct image *image)
Probe SDI image.
Definition sdi.c:97
static int sdi_exec(struct image *image)
Execute SDI image.
Definition sdi.c:53
System Deployment Image (SDI)
#define SDI_BOOT_OFF
SDI boot offset.
Definition sdi.h:34
#define SDI_MAGIC
SDI image signature.
Definition sdi.h:27
#define SDI_WTF
Constant to binary-OR with physical address of SDI image.
Definition sdi.h:37
#define SDI_BOOT_SEG
SDI boot segment.
Definition sdi.h:31
An executable image type.
Definition image.h:95
An executable image.
Definition image.h:24
const void * data
Read-only data.
Definition image.h:51
char * name
Name.
Definition image.h:38
size_t len
Length of raw file image.
Definition image.h:56
SDI image header.
Definition sdi.h:13
uint64_t boot_offset
Boot code offset.
Definition sdi.h:21
uint32_t magic
Signature.
Definition sdi.h:15
uint64_t boot_size
Boot code size.
Definition sdi.h:23