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 
24 FILE_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  */
53 static 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  */
97 static 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 */
119 struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = {
120  .name = "SDI",
121  .probe = sdi_probe,
122  .exec = sdi_exec,
123 };
static int sdi_exec(struct image *image)
Execute SDI image.
Definition: sdi.c:53
#define SDI_BOOT_SEG
SDI boot segment.
Definition: sdi.h:31
System Deployment Image (SDI)
Error codes.
const void * data
Read-only data.
Definition: image.h:50
#define ENOEXEC
Exec format error.
Definition: errno.h:519
#define DBGC(...)
Definition: compiler.h:505
An executable image type.
Definition: image.h:94
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:155
An executable image.
Definition: image.h:23
#define FEATURE_IMAGE
Image formats.
Definition: features.h:22
struct image_type sdi_image_type __image_type(PROBE_NORMAL)
SDI image type.
#define ECANCELED
Operation canceled.
Definition: errno.h:343
char * name
Name of this image type.
Definition: image.h:96
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition: realmode.h:77
uint64_t boot_size
Boot code size.
Definition: sdi.h:23
void * memcpy(void *dest, const void *src, size_t len) __nonnull
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
Executable images.
#define SDI_WTF
Constant to binary-OR with physical address of SDI image.
Definition: sdi.h:37
static int sdi_probe(struct image *image)
Probe SDI image.
Definition: sdi.c:97
Feature list.
size_t len
Length of raw file image.
Definition: image.h:55
uint32_t magic
Signature.
Definition: sdi.h:15
uint64_t boot_offset
Boot code offset.
Definition: sdi.h:21
__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))
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned int uint32_t
Definition: stdint.h:12
SDI image header.
Definition: sdi.h:13
#define SDI_MAGIC
SDI image signature.
Definition: sdi.h:27
__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")
#define DHCP_EB_FEATURE_SDI
SDI image support.
Definition: features.h:56
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
FEATURE(FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1)
#define SDI_BOOT_OFF
SDI boot offset.
Definition: sdi.h:34
#define REAL_CODE(asm_code_str)
Definition: libkir.h:226
char * name
Name.
Definition: image.h:37
String functions.