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