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 <realmode.h>
42 
43 /** Command line physical address
44  *
45  * This can be set by the prefix.
46  */
48 #define cmdline_phys __use_data16 ( cmdline_phys )
49 
50 /** initrd physical address
51  *
52  * This can be set by the prefix.
53  */
55 #define initrd_phys __use_data16 ( initrd_phys )
56 
57 /** initrd length
58  *
59  * This can be set by the prefix.
60  */
62 #define initrd_len __use_data16 ( initrd_len )
63 
64 /** Internal copy of the command line */
65 static char *cmdline_copy;
66 
67 /** Free command line image */
68 static void cmdline_image_free ( struct refcnt *refcnt ) {
69  struct image *image = container_of ( refcnt, struct image, refcnt );
70 
71  DBGC ( image, "RUNTIME freeing command line\n" );
72  free ( cmdline_copy );
73 }
74 
75 /** Embedded script representing the command line */
76 static struct image cmdline_image = {
78  .name = "<CMDLINE>",
79  .type = &script_image_type,
80 };
81 
82 /** Colour for debug messages */
83 #define colour &cmdline_image
84 
85 /**
86  * Strip unwanted cruft from command line
87  *
88  * @v cmdline Command line
89  * @v cruft Initial substring of cruft to strip
90  */
91 static void cmdline_strip ( char *cmdline, const char *cruft ) {
92  char *strip;
93  char *strip_end;
94 
95  /* Find unwanted cruft, if present */
96  if ( ! ( strip = strstr ( cmdline, cruft ) ) )
97  return;
98 
99  /* Strip unwanted cruft */
100  strip_end = strchr ( strip, ' ' );
101  if ( strip_end ) {
102  *strip_end = '\0';
103  DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
104  strcpy ( strip, ( strip_end + 1 ) );
105  } else {
106  DBGC ( colour, "RUNTIME stripping \"%s\"\n", strip );
107  *strip = '\0';
108  }
109 }
110 
111 /**
112  * Initialise command line
113  *
114  * @ret rc Return status code
115  */
116 static int cmdline_init ( void ) {
117  userptr_t cmdline_user;
118  char *cmdline;
119  size_t len;
120  int rc;
121 
122  /* Do nothing if no command line was specified */
123  if ( ! cmdline_phys ) {
124  DBGC ( colour, "RUNTIME found no command line\n" );
125  return 0;
126  }
127  cmdline_user = phys_to_user ( cmdline_phys );
128  len = ( strlen_user ( cmdline_user, 0 ) + 1 /* NUL */ );
129 
130  /* Allocate and copy command line */
131  cmdline_copy = malloc ( len );
132  if ( ! cmdline_copy ) {
133  DBGC ( colour, "RUNTIME could not allocate %zd bytes for "
134  "command line\n", len );
135  rc = -ENOMEM;
136  goto err_alloc_cmdline_copy;
137  }
139  copy_from_user ( cmdline, cmdline_user, 0, len );
140  DBGC ( colour, "RUNTIME found command line \"%s\" at %08x\n",
142 
143  /* Mark command line as consumed */
144  cmdline_phys = 0;
145 
146  /* Strip unwanted cruft from the command line */
147  cmdline_strip ( cmdline, "BOOT_IMAGE=" );
148  cmdline_strip ( cmdline, "initrd=" );
149  while ( isspace ( *cmdline ) )
150  cmdline++;
151  DBGC ( colour, "RUNTIME using command line \"%s\"\n", cmdline );
152 
153  /* Prepare and register image */
156  if ( cmdline_image.len ) {
157  if ( ( rc = register_image ( &cmdline_image ) ) != 0 ) {
158  DBGC ( colour, "RUNTIME could not register command "
159  "line: %s\n", strerror ( rc ) );
160  goto err_register_image;
161  }
162  }
163 
164  /* Drop our reference to the image */
166 
167  return 0;
168 
169  err_register_image:
171  err_alloc_cmdline_copy:
172  return rc;
173 }
174 
175 /**
176  * Initialise initrd
177  *
178  * @ret rc Return status code
179  */
180 static int initrd_init ( void ) {
181  struct image *image;
182 
183  /* Do nothing if no initrd was specified */
184  if ( ! initrd_phys ) {
185  DBGC ( colour, "RUNTIME found no initrd\n" );
186  return 0;
187  }
188  if ( ! initrd_len ) {
189  DBGC ( colour, "RUNTIME found empty initrd\n" );
190  return 0;
191  }
192  DBGC ( colour, "RUNTIME found initrd at [%x,%x)\n",
194 
195  /* Create initrd image */
196  image = image_memory ( "<INITRD>", phys_to_user ( initrd_phys ),
197  initrd_len );
198  if ( ! image ) {
199  DBGC ( colour, "RUNTIME could not create initrd image\n" );
200  return -ENOMEM;
201  }
202 
203  /* Mark initrd as consumed */
204  initrd_phys = 0;
205 
206  return 0;
207 }
208 
209 /**
210  * Initialise command line and initrd
211  *
212  */
213 static void runtime_init ( void ) {
214  int rc;
215 
216  /* Initialise command line */
217  if ( ( rc = cmdline_init() ) != 0 ) {
218  /* No way to report failure */
219  return;
220  }
221 
222  /* Initialise initrd */
223  if ( ( rc = initrd_init() ) != 0 ) {
224  /* No way to report failure */
225  return;
226  }
227 }
228 
229 /** Command line and initrd initialisation function */
230 struct startup_fn runtime_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
231  .name = "runtime",
232  .startup = runtime_init,
233 };
#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:116
struct startup_fn runtime_startup_fn __startup_fn(STARTUP_NORMAL)
Command line and initrd initialisation function.
#define DBGC(...)
Definition: compiler.h:505
struct image * image_memory(const char *name, userptr_t data, size_t len)
Create registered image from block of memory.
Definition: image.c:547
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:180
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:213
A reference counter.
Definition: refcnt.h:26
A startup/shutdown function.
Definition: init.h:41
#define cmdline_phys
Definition: runtime.c:48
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:309
#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:326
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int register_image(struct image *image)
Register executable image.
Definition: image.c:264
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:271
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:243
static void image_put(struct image *image)
Decrement reference count on an image.
Definition: image.h:228
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:76
static void cmdline_strip(char *cmdline, const char *cruft)
Strip unwanted cruft from command line.
Definition: runtime.c:91
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
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:68
#define initrd_phys
Definition: runtime.c:55
uint32_t cmdline
Definition: multiboot.h:16
static char * cmdline_copy
Internal copy of the command line.
Definition: runtime.c:65
uint32_t __bss16(cmdline_phys)
Command line physical address.
#define colour
Colour for debug messages.
Definition: runtime.c:83
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
#define initrd_len
Definition: runtime.c:62
struct refcnt refcnt
Reference count.
Definition: image.h:26