These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / image / sdi.c
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
45 FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 );
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 */
100         memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0,
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 };