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
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.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
28 * Command line and initrd passed to iPXE at runtime
38 #include <ipxe/init.h>
39 #include <ipxe/image.h>
40 #include <ipxe/script.h>
41 #include <ipxe/umalloc.h>
44 /** Command line physical address
46 * This can be set by the prefix.
48 uint32_t __bss16 ( cmdline_phys );
49 #define cmdline_phys __use_data16 ( cmdline_phys )
51 /** initrd physical address
53 * This can be set by the prefix.
55 uint32_t __bss16 ( initrd_phys );
56 #define initrd_phys __use_data16 ( initrd_phys )
60 * This can be set by the prefix.
62 uint32_t __bss16 ( initrd_len );
63 #define initrd_len __use_data16 ( initrd_len )
65 /** Internal copy of the command line */
66 static char *cmdline_copy;
68 /** Free command line image */
69 static void cmdline_image_free ( struct refcnt *refcnt ) {
70 struct image *image = container_of ( refcnt, struct image, refcnt );
72 DBGC ( image, "RUNTIME freeing command line\n" );
73 free ( cmdline_copy );
76 /** Embedded script representing the command line */
77 static struct image cmdline_image = {
78 .refcnt = REF_INIT ( cmdline_image_free ),
80 .type = &script_image_type,
83 /** Colour for debug messages */
84 #define colour &cmdline_image
87 * Strip unwanted cruft from command line
89 * @v cmdline Command line
90 * @v cruft Initial substring of cruft to strip
92 static void cmdline_strip ( char *cmdline, const char *cruft ) {
96 /* Find unwanted cruft, if present */
97 if ( ! ( strip = strstr ( cmdline, cruft ) ) )
100 /* Strip unwanted cruft */
101 strip_end = strchr ( strip, ' ' );
104 DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
105 strcpy ( strip, ( strip_end + 1 ) );
107 DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
113 * Initialise command line
115 * @ret rc Return status code
117 static int cmdline_init ( void ) {
118 userptr_t cmdline_user;
123 /* Do nothing if no command line was specified */
124 if ( ! cmdline_phys ) {
125 DBGC ( colour, "RUNTIME found no command line\n" );
128 cmdline_user = phys_to_user ( cmdline_phys );
129 len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
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 );
137 goto err_alloc_cmdline_copy;
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 );
144 /* Mark command line as consumed */
147 /* Strip unwanted cruft from the command line */
148 cmdline_strip ( cmdline, "BOOT_IMAGE=" );
149 cmdline_strip ( cmdline, "initrd=" );
150 while ( isspace ( *cmdline ) )
152 DBGC ( colour, "RUNTIME using command line \"%s\"\n", cmdline );
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;
165 /* Drop our reference to the image */
166 image_put ( &cmdline_image );
171 image_put ( &cmdline_image );
172 err_alloc_cmdline_copy:
179 * @ret rc Return status code
181 static int initrd_init ( void ) {
185 /* Do nothing if no initrd was specified */
186 if ( ! initrd_phys ) {
187 DBGC ( colour, "RUNTIME found no initrd\n" );
190 if ( ! initrd_len ) {
191 DBGC ( colour, "RUNTIME found empty initrd\n" );
194 DBGC ( colour, "RUNTIME found initrd at [%x,%x)\n",
195 initrd_phys, ( initrd_phys + initrd_len ) );
198 image = alloc_image ( NULL );
200 DBGC ( colour, "RUNTIME could not allocate image for "
203 goto err_alloc_image;
205 if ( ( rc = image_set_name ( image, "<INITRD>" ) ) != 0 ) {
206 DBGC ( colour, "RUNTIME could not set image name: %s\n",
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 );
219 image->len = initrd_len;
220 memcpy_user ( image->data, 0, phys_to_user ( initrd_phys ), 0,
223 /* Mark initrd as consumed */
227 if ( ( rc = register_image ( image ) ) != 0 ) {
228 DBGC ( colour, "RUNTIME could not register initrd: %s\n",
230 goto err_register_image;
233 /* Drop our reference to the image */
247 * Initialise command line and initrd
250 static void runtime_init ( void ) {
253 /* Initialise command line */
254 if ( ( rc = cmdline_init() ) != 0 ) {
255 /* No way to report failure */
259 /* Initialise initrd */
260 if ( ( rc = initrd_init() ) != 0 ) {
261 /* No way to report failure */
266 /** Command line and initrd initialisation function */
267 struct startup_fn runtime_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
268 .startup = runtime_init,