iPXE
runtime.c
Go to the documentation of this file.
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  */
49 #define cmdline_phys __use_data16 ( cmdline_phys )
50 
51 /** initrd physical address
52  *
53  * This can be set by the prefix.
54  */
56 #define initrd_phys __use_data16 ( initrd_phys )
57 
58 /** initrd length
59  *
60  * This can be set by the prefix.
61  */
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 = {
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  }
140  copy_from_user ( cmdline, cmdline_user, 0, len );
141  DBGC ( colour, "RUNTIME found command line \"%s\" at %08x\n",
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 */
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 */
167 
168  return 0;
169 
170  err_register_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",
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;
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  .name = "runtime",
269  .startup = runtime_init,
270 };
#define STARTUP_NORMAL
Normal startup.
Definition: init.h:63
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
userptr_t data
Raw file image.
Definition: image.h:41
Error codes.
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
static int cmdline_init(void)
Initialise command line.
Definition: runtime.c:117
struct startup_fn runtime_startup_fn __startup_fn(STARTUP_NORMAL)
Command line and initrd initialisation function.
#define DBGC(...)
Definition: compiler.h:505
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
static int initrd_init(void)
Initialise initrd.
Definition: runtime.c:181
An executable image.
Definition: image.h:24
Character types.
const char * name
Definition: init.h:42
iPXE scripts
static void runtime_init(void)
Initialise command line and initrd.
Definition: runtime.c:250
A reference counter.
Definition: refcnt.h:26
A startup/shutdown function.
Definition: init.h:41
#define cmdline_phys
Definition: runtime.c:49
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:279
#define ENOMEM
Not enough space.
Definition: errno.h:534
Assertions.
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
Executable images.
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:296
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int register_image(struct image *image)
Register executable image.
Definition: image.c:210
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
size_t len
Length of raw file image.
Definition: image.h:43
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:241
int image_set_name(struct image *image, const char *name)
Set image name.
Definition: image.c:144
User memory allocation.
int isspace(int character)
Check to see if character is a space.
Definition: ctype.c:41
size_t strlen(const char *src)
Get length of string.
Definition: string.c:213
static void image_put(struct image *image)
Decrement reference count on an image.
Definition: image.h:206
unsigned int uint32_t
Definition: stdint.h:12
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
static struct image cmdline_image
Embedded script representing the command line.
Definition: runtime.c:77
static void cmdline_strip(char *cmdline, const char *cruft)
Strip unwanted cruft from command line.
Definition: runtime.c:92
size_t strlen_user(userptr_t userptr, off_t offset)
Find length of NUL-terminated string in user buffer.
uint32_t len
Length.
Definition: ena.h:14
static __always_inline userptr_t umalloc(size_t size)
Allocate external memory.
Definition: umalloc.h:54
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
#define REF_INIT(free_fn)
Initialise a static reference counter.
Definition: refcnt.h:77
static void cmdline_image_free(struct refcnt *refcnt)
Free command line image.
Definition: runtime.c:69
#define initrd_phys
Definition: runtime.c:56
uint32_t cmdline
Definition: multiboot.h:16
struct image * alloc_image(struct uri *uri)
Allocate executable image.
Definition: image.c:90
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
static char * cmdline_copy
Internal copy of the command line.
Definition: runtime.c:66
uint32_t __bss16(cmdline_phys)
Command line physical address.
#define colour
Colour for debug messages.
Definition: runtime.c:84
void memcpy_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers.
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
#define initrd_len
Definition: runtime.c:63
struct refcnt refcnt
Reference count.
Definition: image.h:26