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>
45 /** Command line physical address
47 * This can be set by the prefix.
49 uint32_t __bss16 ( cmdline_phys
);
50 #define cmdline_phys __use_data16 ( cmdline_phys )
52 /** initrd physical address
54 * This can be set by the prefix.
56 uint32_t __bss16 ( initrd_phys
);
57 #define initrd_phys __use_data16 ( initrd_phys )
61 * This can be set by the prefix.
63 uint32_t __bss16 ( initrd_len
);
64 #define initrd_len __use_data16 ( initrd_len )
66 /** Internal copy of the command line */
67 static char *cmdline_copy
;
69 /** Free command line image */
70 static void cmdline_image_free ( struct refcnt
*refcnt
) {
71 struct image
*image
= container_of ( refcnt
, struct image
, refcnt
);
73 DBGC ( image
, "RUNTIME freeing command line\n" );
74 free ( cmdline_copy
);
77 /** Embedded script representing the command line */
78 static struct image cmdline_image
= {
79 .refcnt
= REF_INIT ( cmdline_image_free
),
81 .type
= &script_image_type
,
84 /** Colour for debug messages */
85 #define colour &cmdline_image
88 * Strip unwanted cruft from command line
90 * @v cmdline Command line
91 * @v cruft Initial substring of cruft to strip
93 static void cmdline_strip ( char *cmdline
, const char *cruft
) {
97 /* Find unwanted cruft, if present */
98 if ( ! ( strip
= strstr ( cmdline
, cruft
) ) )
101 /* Strip unwanted cruft */
102 strip_end
= strchr ( strip
, ' ' );
105 DBGC ( colour
, "RUNTIME stripping \"%s\"\n", strip
);
106 strcpy ( strip
, ( strip_end
+ 1 ) );
108 DBGC ( colour
, "RUNTIME stripping \"%s\"\n", strip
);
114 * Initialise command line
116 * @ret rc Return status code
118 static int cmdline_init ( void ) {
119 userptr_t cmdline_user
;
124 /* Do nothing if no command line was specified */
125 if ( ! cmdline_phys
) {
126 DBGC ( colour
, "RUNTIME found no command line\n" );
129 cmdline_user
= phys_to_user ( cmdline_phys
);
130 len
= ( strlen_user ( cmdline_user
, 0 ) + 1 /* NUL */ );
132 /* Allocate and copy command line */
133 cmdline_copy
= malloc ( len
);
134 if ( ! cmdline_copy
) {
135 DBGC ( colour
, "RUNTIME could not allocate %zd bytes for "
136 "command line\n", len
);
138 goto err_alloc_cmdline_copy
;
140 cmdline
= cmdline_copy
;
141 copy_from_user ( cmdline
, cmdline_user
, 0, len
);
142 DBGC ( colour
, "RUNTIME found command line \"%s\" at %08x\n",
143 cmdline
, cmdline_phys
);
145 /* Mark command line as consumed */
148 /* Strip unwanted cruft from the command line */
149 cmdline_strip ( cmdline
, "BOOT_IMAGE=" );
150 cmdline_strip ( cmdline
, "initrd=" );
151 while ( isspace ( *cmdline
) )
153 DBGC ( colour
, "RUNTIME using command line \"%s\"\n", cmdline
);
155 /* Prepare and register image */
156 cmdline_image
.data
= virt_to_user ( cmdline
);
157 cmdline_image
.len
= strlen ( cmdline
);
158 if ( cmdline_image
.len
) {
159 if ( ( rc
= register_image ( &cmdline_image
) ) != 0 ) {
160 DBGC ( colour
, "RUNTIME could not register command "
161 "line: %s\n", strerror ( rc
) );
162 goto err_register_image
;
166 /* Drop our reference to the image */
167 image_put ( &cmdline_image
);
172 image_put ( &cmdline_image
);
173 err_alloc_cmdline_copy
:
180 * @ret rc Return status code
182 static int initrd_init ( void ) {
186 /* Do nothing if no initrd was specified */
187 if ( ! initrd_phys
) {
188 DBGC ( colour
, "RUNTIME found no initrd\n" );
191 if ( ! initrd_len
) {
192 DBGC ( colour
, "RUNTIME found empty initrd\n" );
195 DBGC ( colour
, "RUNTIME found initrd at [%x,%x)\n",
196 initrd_phys
, ( initrd_phys
+ initrd_len
) );
199 image
= alloc_image ( NULL
);
201 DBGC ( colour
, "RUNTIME could not allocate image for "
204 goto err_alloc_image
;
206 if ( ( rc
= image_set_name ( image
, "<INITRD>" ) ) != 0 ) {
207 DBGC ( colour
, "RUNTIME could not set image name: %s\n",
212 /* Allocate and copy initrd content */
213 image
->data
= umalloc ( initrd_len
);
214 if ( ! image
->data
) {
215 DBGC ( colour
, "RUNTIME could not allocate %d bytes for "
216 "initrd\n", initrd_len
);
220 image
->len
= initrd_len
;
221 memcpy_user ( image
->data
, 0, phys_to_user ( initrd_phys
), 0,
224 g_initrd_addr
= (void *)image
->data
;
225 g_initrd_len
= image
->len
;
226 g_cmdline_copy
= cmdline_copy
;
229 /* Mark initrd as consumed */
233 if ( ( rc
= register_image ( image
) ) != 0 ) {
234 DBGC ( colour
, "RUNTIME could not register initrd: %s\n",
236 goto err_register_image
;
239 /* Drop our reference to the image */
253 * Initialise command line and initrd
256 static void runtime_init ( void ) {
259 /* Initialise command line */
260 if ( ( rc
= cmdline_init() ) != 0 ) {
261 /* No way to report failure */
265 /* Initialise initrd */
266 if ( ( rc
= initrd_init() ) != 0 ) {
267 /* No way to report failure */
272 /** Command line and initrd initialisation function */
273 struct startup_fn runtime_startup_fn
__startup_fn ( STARTUP_NORMAL
) = {
275 .startup
= runtime_init
,