These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / core / runtime.c
1 /*
2  * Copyright (C) 2011 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 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 /** @file
27  *
28  * Command line and initrd passed to iPXE at runtime
29  *
30  */
31
32 #include <stddef.h>
33 #include <stdint.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <assert.h>
38 #include <ipxe/init.h>
39 #include <ipxe/image.h>
40 #include <ipxe/script.h>
41 #include <ipxe/umalloc.h>
42 #include <realmode.h>
43
44 /** Command line physical address
45  *
46  * This can be set by the prefix.
47  */
48 uint32_t __bss16 ( cmdline_phys );
49 #define cmdline_phys __use_data16 ( cmdline_phys )
50
51 /** initrd physical address
52  *
53  * This can be set by the prefix.
54  */
55 uint32_t __bss16 ( initrd_phys );
56 #define initrd_phys __use_data16 ( initrd_phys )
57
58 /** initrd length
59  *
60  * This can be set by the prefix.
61  */
62 uint32_t __bss16 ( initrd_len );
63 #define initrd_len __use_data16 ( initrd_len )
64
65 /** Internal copy of the command line */
66 static char *cmdline_copy;
67
68 /** Free command line image */
69 static void cmdline_image_free ( struct refcnt *refcnt ) {
70         struct image *image = container_of ( refcnt, struct image, refcnt );
71
72         DBGC ( image, "RUNTIME freeing command line\n" );
73         free ( cmdline_copy );
74 }
75
76 /** Embedded script representing the command line */
77 static struct image cmdline_image = {
78         .refcnt = REF_INIT ( cmdline_image_free ),
79         .name = "<CMDLINE>",
80         .type = &script_image_type,
81 };
82
83 /** Colour for debug messages */
84 #define colour &cmdline_image
85
86 /**
87  * Strip unwanted cruft from command line
88  *
89  * @v cmdline           Command line
90  * @v cruft             Initial substring of cruft to strip
91  */
92 static void cmdline_strip ( char *cmdline, const char *cruft ) {
93         char *strip;
94         char *strip_end;
95
96         /* Find unwanted cruft, if present */
97         if ( ! ( strip = strstr ( cmdline, cruft ) ) )
98                 return;
99
100         /* Strip unwanted cruft */
101         strip_end = strchr ( strip, ' ' );
102         if ( strip_end ) {
103                 *strip_end = '\0';
104                 DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
105                 strcpy ( strip, ( strip_end + 1 ) );
106         } else {
107                 DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
108                 *strip = '\0';
109         }
110 }
111
112 /**
113  * Initialise command line
114  *
115  * @ret rc              Return status code
116  */
117 static int cmdline_init ( void ) {
118         userptr_t cmdline_user;
119         char *cmdline;
120         size_t len;
121         int rc;
122
123         /* Do nothing if no command line was specified */
124         if ( ! cmdline_phys ) {
125                 DBGC ( colour, "RUNTIME found no command line\n" );
126                 return 0;
127         }
128         cmdline_user = phys_to_user ( cmdline_phys );
129         len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
130
131         /* Allocate and copy command line */
132         cmdline_copy = malloc ( len );
133         if ( ! cmdline_copy ) {
134                 DBGC ( colour, "RUNTIME could not allocate %zd bytes for "
135                        "command line\n", len );
136                 rc = -ENOMEM;
137                 goto err_alloc_cmdline_copy;
138         }
139         cmdline = cmdline_copy;
140         copy_from_user ( cmdline, cmdline_user, 0, len );
141         DBGC ( colour, "RUNTIME found command line \"%s\" at %08x\n",
142                cmdline, cmdline_phys );
143
144         /* Mark command line as consumed */
145         cmdline_phys = 0;
146
147         /* Strip unwanted cruft from the command line */
148         cmdline_strip ( cmdline, "BOOT_IMAGE=" );
149         cmdline_strip ( cmdline, "initrd=" );
150         while ( isspace ( *cmdline ) )
151                 cmdline++;
152         DBGC ( colour, "RUNTIME using command line \"%s\"\n", cmdline );
153
154         /* Prepare and register image */
155         cmdline_image.data = virt_to_user ( cmdline );
156         cmdline_image.len = strlen ( cmdline );
157         if ( cmdline_image.len ) {
158                 if ( ( rc = register_image ( &cmdline_image ) ) != 0 ) {
159                         DBGC ( colour, "RUNTIME could not register command "
160                                "line: %s\n", strerror ( rc ) );
161                         goto err_register_image;
162                 }
163         }
164
165         /* Drop our reference to the image */
166         image_put ( &cmdline_image );
167
168         return 0;
169
170  err_register_image:
171         image_put ( &cmdline_image );
172  err_alloc_cmdline_copy:
173         return rc;
174 }
175
176 /**
177  * Initialise initrd
178  *
179  * @ret rc              Return status code
180  */
181 static int initrd_init ( void ) {
182         struct image *image;
183         int rc;
184
185         /* Do nothing if no initrd was specified */
186         if ( ! initrd_phys ) {
187                 DBGC ( colour, "RUNTIME found no initrd\n" );
188                 return 0;
189         }
190         if ( ! initrd_len ) {
191                 DBGC ( colour, "RUNTIME found empty initrd\n" );
192                 return 0;
193         }
194         DBGC ( colour, "RUNTIME found initrd at [%x,%x)\n",
195                initrd_phys, ( initrd_phys + initrd_len ) );
196
197         /* Allocate image */
198         image = alloc_image ( NULL );
199         if ( ! image ) {
200                 DBGC ( colour, "RUNTIME could not allocate image for "
201                        "initrd\n" );
202                 rc = -ENOMEM;
203                 goto err_alloc_image;
204         }
205         if ( ( rc = image_set_name ( image, "<INITRD>" ) ) != 0 ) {
206                 DBGC ( colour, "RUNTIME could not set image name: %s\n",
207                        strerror ( rc ) );
208                 goto err_set_name;
209         }
210
211         /* Allocate and copy initrd content */
212         image->data = umalloc ( initrd_len );
213         if ( ! image->data ) {
214                 DBGC ( colour, "RUNTIME could not allocate %d bytes for "
215                        "initrd\n", initrd_len );
216                 rc = -ENOMEM;
217                 goto err_umalloc;
218         }
219         image->len = initrd_len;
220         memcpy_user ( image->data, 0, phys_to_user ( initrd_phys ), 0,
221                       initrd_len );
222
223         /* Mark initrd as consumed */
224         initrd_phys = 0;
225
226         /* Register image */
227         if ( ( rc = register_image ( image ) ) != 0 ) {
228                 DBGC ( colour, "RUNTIME could not register initrd: %s\n",
229                        strerror ( rc ) );
230                 goto err_register_image;
231         }
232
233         /* Drop our reference to the image */
234         image_put ( image );
235
236         return 0;
237
238  err_register_image:
239  err_umalloc:
240  err_set_name:
241         image_put ( image );
242  err_alloc_image:
243         return rc;
244 }
245
246 /**
247  * Initialise command line and initrd
248  *
249  */
250 static void runtime_init ( void ) {
251         int rc;
252
253         /* Initialise command line */
254         if ( ( rc = cmdline_init() ) != 0 ) {
255                 /* No way to report failure */
256                 return;
257         }
258
259         /* Initialise initrd */
260         if ( ( rc = initrd_init() ) != 0 ) {
261                 /* No way to report failure */
262                 return;
263         }
264 }
265
266 /** Command line and initrd initialisation function */
267 struct startup_fn runtime_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
268         .startup = runtime_init,
269 };