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  * Parse SDI image header
49  *
50  * @v image SDI file
51  * @v sdi SDI header to fill in
52  * @ret rc Return status code
53  */
54 static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) {
55 
56  /* Sanity check */
57  if ( image->len < sizeof ( *sdi ) ) {
58  DBGC ( image, "SDI %p too short for SDI header\n", image );
59  return -ENOEXEC;
60  }
61 
62  /* Read in header */
63  copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) );
64 
65  /* Check signature */
66  if ( sdi->magic != SDI_MAGIC ) {
67  DBGC ( image, "SDI %p is not an SDI image\n", image );
68  return -ENOEXEC;
69  }
70 
71  return 0;
72 }
73 
74 /**
75  * Execute SDI image
76  *
77  * @v image SDI file
78  * @ret rc Return status code
79  */
80 static int sdi_exec ( struct image *image ) {
81  struct sdi_header sdi;
82  uint32_t sdiptr;
83  int rc;
84 
85  /* Parse image header */
86  if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
87  return rc;
88 
89  /* Check that image is bootable */
90  if ( sdi.boot_size == 0 ) {
91  DBGC ( image, "SDI %p is not bootable\n", image );
92  return -ENOTTY;
93  }
94  DBGC ( image, "SDI %p image at %08lx+%08zx\n",
95  image, user_to_phys ( image->data, 0 ), image->len );
96  DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image,
97  user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size );
98 
99  /* Copy boot code */
101  image->data, sdi.boot_offset, sdi.boot_size );
102 
103  /* Jump to boot code */
104  sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF );
105  __asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" )
106  : : "i" ( SDI_BOOT_SEG ),
107  "i" ( SDI_BOOT_OFF ),
108  "d" ( sdiptr ) );
109 
110  /* There is no way for the image to return, since we provide
111  * no return address.
112  */
113  assert ( 0 );
114 
115  return -ECANCELED; /* -EIMPOSSIBLE */
116 }
117 
118 /**
119  * Probe SDI image
120  *
121  * @v image SDI file
122  * @ret rc Return status code
123  */
124 static int sdi_probe ( struct image *image ) {
125  struct sdi_header sdi;
126  int rc;
127 
128  /* Parse image */
129  if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
130  return rc;
131 
132  return 0;
133 }
134 
135 /** SDI image type */
136 struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = {
137  .name = "SDI",
138  .probe = sdi_probe,
139  .exec = sdi_exec,
140 };
static int sdi_exec(struct image *image)
Execute SDI image.
Definition: sdi.c:80
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define SDI_BOOT_SEG
SDI boot segment.
Definition: sdi.h:31
userptr_t data
Raw file image.
Definition: image.h:41
System Deployment Image (SDI)
Error codes.
#define ENOEXEC
Exec format error.
Definition: errno.h:519
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
#define DBGC(...)
Definition: compiler.h:505
An executable image type.
Definition: image.h:76
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:137
An executable image.
Definition: image.h:24
#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:78
uint64_t boot_size
Boot code size.
Definition: sdi.h:23
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:124
Feature list.
size_t len
Length of raw file image.
Definition: image.h:43
uint32_t magic
Signature.
Definition: sdi.h:15
uint64_t boot_offset
Boot code offset.
Definition: sdi.h:21
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
__asm__ __volatile__("\n1:\n\t" "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %4, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c), "+m"(*value) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
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)
static __always_inline userptr_t real_to_user(unsigned int segment, unsigned int offset)
Convert segment:offset address to user buffer.
Definition: realmode.h:75
#define SDI_BOOT_OFF
SDI boot offset.
Definition: sdi.h:34
#define REAL_CODE(asm_code_str)
Definition: libkir.h:226
String functions.
static int sdi_parse_header(struct image *image, struct sdi_header *sdi)
Parse SDI image header.
Definition: sdi.c:54
void memcpy_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers.