2 * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
20 FILE_LICENCE ( GPL2_OR_LATER );
24 * Command line and initrd passed to iPXE at runtime
34 #include <ipxe/init.h>
35 #include <ipxe/image.h>
36 #include <ipxe/script.h>
37 #include <ipxe/umalloc.h>
40 /** Command line physical address
42 * This can be set by the prefix.
44 uint32_t __bss16 ( cmdline_phys );
45 #define cmdline_phys __use_data16 ( cmdline_phys )
47 /** initrd physical address
49 * This can be set by the prefix.
51 uint32_t __bss16 ( initrd_phys );
52 #define initrd_phys __use_data16 ( initrd_phys )
56 * This can be set by the prefix.
58 uint32_t __bss16 ( initrd_len );
59 #define initrd_len __use_data16 ( initrd_len )
61 /** Internal copy of the command line */
62 static char *cmdline_copy;
64 /** Free command line image */
65 static void cmdline_image_free ( struct refcnt *refcnt ) {
66 struct image *image = container_of ( refcnt, struct image, refcnt );
68 DBGC ( image, "RUNTIME freeing command line\n" );
69 free ( cmdline_copy );
72 /** Embedded script representing the command line */
73 static struct image cmdline_image = {
74 .refcnt = REF_INIT ( cmdline_image_free ),
76 .type = &script_image_type,
79 /** Colour for debug messages */
80 #define colour &cmdline_image
83 * Strip unwanted cruft from command line
85 * @v cmdline Command line
86 * @v cruft Initial substring of cruft to strip
88 static void cmdline_strip ( char *cmdline, const char *cruft ) {
92 /* Find unwanted cruft, if present */
93 if ( ! ( strip = strstr ( cmdline, cruft ) ) )
96 /* Strip unwanted cruft */
97 strip_end = strchr ( strip, ' ' );
100 DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
101 strcpy ( strip, ( strip_end + 1 ) );
103 DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
109 * Initialise command line
111 * @ret rc Return status code
113 static int cmdline_init ( void ) {
114 userptr_t cmdline_user;
119 /* Do nothing if no command line was specified */
120 if ( ! cmdline_phys ) {
121 DBGC ( colour, "RUNTIME found no command line\n" );
124 cmdline_user = phys_to_user ( cmdline_phys );
125 len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
127 /* Allocate and copy command line */
128 cmdline_copy = malloc ( len );
129 if ( ! cmdline_copy ) {
130 DBGC ( colour, "RUNTIME could not allocate %zd bytes for "
131 "command line\n", len );
133 goto err_alloc_cmdline_copy;
135 cmdline = cmdline_copy;
136 copy_from_user ( cmdline, cmdline_user, 0, len );
137 DBGC ( colour, "RUNTIME found command line \"%s\" at %08x\n",
138 cmdline, cmdline_phys );
140 /* Mark command line as consumed */
143 /* Strip unwanted cruft from the command line */
144 cmdline_strip ( cmdline, "BOOT_IMAGE=" );
145 cmdline_strip ( cmdline, "initrd=" );
146 while ( isspace ( *cmdline ) )
148 DBGC ( colour, "RUNTIME using command line \"%s\"\n", cmdline );
150 /* Prepare and register image */
151 cmdline_image.data = virt_to_user ( cmdline );
152 cmdline_image.len = strlen ( cmdline );
153 if ( cmdline_image.len ) {
154 if ( ( rc = register_image ( &cmdline_image ) ) != 0 ) {
155 DBGC ( colour, "RUNTIME could not register command "
156 "line: %s\n", strerror ( rc ) );
157 goto err_register_image;
161 /* Drop our reference to the image */
162 image_put ( &cmdline_image );
167 image_put ( &cmdline_image );
168 err_alloc_cmdline_copy:
175 * @ret rc Return status code
177 static int initrd_init ( void ) {
181 /* Do nothing if no initrd was specified */
182 if ( ! initrd_phys ) {
183 DBGC ( colour, "RUNTIME found no initrd\n" );
186 if ( ! initrd_len ) {
187 DBGC ( colour, "RUNTIME found empty initrd\n" );
190 DBGC ( colour, "RUNTIME found initrd at [%x,%x)\n",
191 initrd_phys, ( initrd_phys + initrd_len ) );
194 image = alloc_image ( NULL );
196 DBGC ( colour, "RUNTIME could not allocate image for "
199 goto err_alloc_image;
201 if ( ( rc = image_set_name ( image, "<INITRD>" ) ) != 0 ) {
202 DBGC ( colour, "RUNTIME could not set image name: %s\n",
207 /* Allocate and copy initrd content */
208 image->data = umalloc ( initrd_len );
209 if ( ! image->data ) {
210 DBGC ( colour, "RUNTIME could not allocate %d bytes for "
211 "initrd\n", initrd_len );
215 image->len = initrd_len;
216 memcpy_user ( image->data, 0, phys_to_user ( initrd_phys ), 0,
219 /* Mark initrd as consumed */
223 if ( ( rc = register_image ( image ) ) != 0 ) {
224 DBGC ( colour, "RUNTIME could not register initrd: %s\n",
226 goto err_register_image;
229 /* Drop our reference to the image */
243 * Initialise command line and initrd
246 static void runtime_init ( void ) {
249 /* Initialise command line */
250 if ( ( rc = cmdline_init() ) != 0 ) {
251 /* No way to report failure */
255 /* Initialise initrd */
256 if ( ( rc = initrd_init() ) != 0 ) {
257 /* No way to report failure */
262 /** Command line and initrd initialisation function */
263 struct startup_fn runtime_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
264 .startup = runtime_init,