2 * Copyright (C) 2006 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
);
29 #include <ipxe/netdevice.h>
30 #include <ipxe/dhcp.h>
31 #include <ipxe/settings.h>
32 #include <ipxe/image.h>
33 #include <ipxe/sanboot.h>
35 #include <ipxe/open.h>
36 #include <ipxe/init.h>
37 #include <ipxe/keys.h>
38 #include <ipxe/version.h>
39 #include <ipxe/shell.h>
40 #include <ipxe/features.h>
41 #include <ipxe/image.h>
42 #include <ipxe/timer.h>
43 #include <usr/ifmgmt.h>
44 #include <usr/route.h>
45 #include <usr/imgmgmt.h>
46 #include <usr/prompt.h>
47 #include <usr/autoboot.h>
48 #include <config/general.h>
49 #include <config/branding.h>
57 /** Link-layer address of preferred autoboot device, if known */
58 static uint8_t autoboot_ll_addr
[MAX_LL_ADDR_LEN
];
60 /** Device location of preferred autoboot device, if known */
61 static struct device_description autoboot_desc
;
63 /** Autoboot device tester */
64 static int ( * is_autoboot_device
) ( struct net_device
*netdev
);
66 /* Disambiguate the various error causes */
67 #define ENOENT_BOOT __einfo_error ( EINFO_ENOENT_BOOT )
68 #define EINFO_ENOENT_BOOT \
69 __einfo_uniqify ( EINFO_ENOENT, 0x01, "Nothing to boot" )
71 #define NORMAL "\033[0m"
72 #define BOLD "\033[1m"
73 #define CYAN "\033[36m"
75 /** The "scriptlet" setting */
76 const struct setting scriptlet_setting
__setting ( SETTING_MISC
, scriptlet
) = {
78 .description
= "Boot scriptlet",
79 .tag
= DHCP_EB_SCRIPTLET
,
80 .type
= &setting_type_string
,
84 * Perform PXE menu boot when PXE stack is not available
86 __weak
int pxe_menu_boot ( struct net_device
*netdev __unused
) {
91 * Parse next-server and filename into a URI
93 * @v next_server Next-server address
94 * @v filename Filename
95 * @ret uri URI, or NULL on failure
97 static struct uri
* parse_next_server_and_filename ( struct in_addr next_server
,
98 const char *filename
) {
102 uri
= parse_uri ( filename
);
106 /* Construct a TFTP URI for the filename, if applicable */
107 if ( next_server
.s_addr
&& filename
[0] && ! uri_is_absolute ( uri
) ) {
109 uri
= tftp_uri ( next_server
, 0, filename
);
117 /** The "keep-san" setting */
118 const struct setting keep_san_setting
__setting ( SETTING_SANBOOT_EXTRA
,
121 .description
= "Preserve SAN connection",
122 .tag
= DHCP_EB_KEEP_SAN
,
123 .type
= &setting_type_int8
,
126 /** The "skip-san-boot" setting */
127 const struct setting skip_san_boot_setting
__setting ( SETTING_SANBOOT_EXTRA
,
129 .name
= "skip-san-boot",
130 .description
= "Do not boot from SAN device",
131 .tag
= DHCP_EB_SKIP_SAN_BOOT
,
132 .type
= &setting_type_int8
,
136 * Boot from filename and root-path URIs
138 * @v filename Filename
139 * @v root_path Root path
140 * @v drive SAN drive (if applicable)
141 * @v flags Boot action flags
142 * @ret rc Return status code
144 * The somewhat tortuous flow of control in this function exists in
145 * order to ensure that the "sanboot" command remains identical in
146 * function to a SAN boot via a DHCP-specified root path, and to
147 * provide backwards compatibility for the "keep-san" and
148 * "skip-san-boot" options.
150 int uriboot ( struct uri
*filename
, struct uri
*root_path
, int drive
,
151 unsigned int flags
) {
155 /* Hook SAN device, if applicable */
157 if ( ( rc
= san_hook ( root_path
, drive
) ) != 0 ) {
158 printf ( "Could not open SAN device: %s\n",
162 printf ( "Registered SAN device %#02x\n", drive
);
165 /* Describe SAN device, if applicable */
166 if ( ( drive
>= 0 ) && ! ( flags
& URIBOOT_NO_SAN_DESCRIBE
) ) {
167 if ( ( rc
= san_describe ( drive
) ) != 0 ) {
168 printf ( "Could not describe SAN device %#02x: %s\n",
169 drive
, strerror ( rc
) );
170 goto err_san_describe
;
174 /* Allow a root-path-only boot with skip-san enabled to succeed */
177 /* Attempt filename boot if applicable */
179 if ( ( rc
= imgdownload ( filename
, 0, &image
) ) != 0 )
181 image
->flags
|= IMAGE_AUTO_UNREGISTER
;
182 if ( ( rc
= image_exec ( image
) ) != 0 ) {
183 printf ( "Could not boot image: %s\n",
185 /* Fall through to (possibly) attempt a SAN boot
186 * as a fallback. If no SAN boot is attempted,
187 * our status will become the return status.
190 /* Always print an extra newline, because we
191 * don't know where the NBP may have left the
198 /* Attempt SAN boot if applicable */
199 if ( ( drive
>= 0 ) && ! ( flags
& URIBOOT_NO_SAN_BOOT
) ) {
200 if ( fetch_intz_setting ( NULL
, &skip_san_boot_setting
) == 0 ) {
201 printf ( "Booting from SAN device %#02x\n", drive
);
202 rc
= san_boot ( drive
);
203 printf ( "Boot from SAN device %#02x failed: %s\n",
204 drive
, strerror ( rc
) );
206 printf ( "Skipping boot from SAN device %#02x\n",
208 /* Avoid overwriting a possible failure status
209 * from a filename boot.
216 /* Unhook SAN device, if applicable */
217 if ( ( drive
>= 0 ) && ! ( flags
& URIBOOT_NO_SAN_UNHOOK
) ) {
218 if ( fetch_intz_setting ( NULL
, &keep_san_setting
) == 0 ) {
219 san_unhook ( drive
);
220 printf ( "Unregistered SAN device %#02x\n", drive
);
222 printf ( "Preserving SAN device %#02x\n", drive
);
230 * Close all open net devices
232 * Called before a fresh boot attempt in order to free up memory. We
233 * don't just close the device immediately after the boot fails,
234 * because there may still be TCP connections in the process of
237 static void close_all_netdevs ( void ) {
238 struct net_device
*netdev
;
240 for_each_netdev ( netdev
) {
246 * Fetch next-server and filename settings into a URI
248 * @v settings Settings block
249 * @ret uri URI, or NULL on failure
251 struct uri
* fetch_next_server_and_filename ( struct settings
*settings
) {
252 struct in_addr next_server
= { 0 };
253 char *raw_filename
= NULL
;
254 struct uri
*uri
= NULL
;
257 /* If we have a filename, fetch it along with the next-server
258 * setting from the same settings block.
260 if ( fetch_setting ( settings
, &filename_setting
, &settings
,
261 NULL
, NULL
, 0 ) >= 0 ) {
262 fetch_string_setting_copy ( settings
, &filename_setting
,
264 fetch_ipv4_setting ( settings
, &next_server_setting
,
268 /* Expand filename setting */
269 filename
= expand_settings ( raw_filename ? raw_filename
: "" );
273 /* Parse next server and filename */
274 if ( next_server
.s_addr
)
275 printf ( "Next server: %s\n", inet_ntoa ( next_server
) );
277 printf ( "Filename: %s\n", filename
);
278 uri
= parse_next_server_and_filename ( next_server
, filename
);
285 free ( raw_filename
);
290 * Fetch root-path setting into a URI
292 * @v settings Settings block
293 * @ret uri URI, or NULL on failure
295 static struct uri
* fetch_root_path ( struct settings
*settings
) {
296 struct uri
*uri
= NULL
;
300 /* Fetch root-path setting */
301 fetch_string_setting_copy ( settings
, &root_path_setting
,
304 /* Expand filename setting */
305 root_path
= expand_settings ( raw_root_path ? raw_root_path
: "" );
309 /* Parse root path */
311 printf ( "Root path: %s\n", root_path
);
312 uri
= parse_uri ( root_path
);
319 free ( raw_root_path
);
324 * Check whether or not we have a usable PXE menu
326 * @ret have_menu A usable PXE menu is present
328 static int have_pxe_menu ( void ) {
329 struct setting vendor_class_id_setting
330 = { .tag
= DHCP_VENDOR_CLASS_ID
};
331 struct setting pxe_discovery_control_setting
332 = { .tag
= DHCP_PXE_DISCOVERY_CONTROL
};
333 struct setting pxe_boot_menu_setting
334 = { .tag
= DHCP_PXE_BOOT_MENU
};
335 char buf
[ 10 /* "PXEClient" + NUL */ ];
336 unsigned int pxe_discovery_control
;
338 fetch_string_setting ( NULL
, &vendor_class_id_setting
,
339 buf
, sizeof ( buf
) );
340 pxe_discovery_control
=
341 fetch_uintz_setting ( NULL
, &pxe_discovery_control_setting
);
343 return ( ( strcmp ( buf
, "PXEClient" ) == 0 ) &&
344 setting_exists ( NULL
, &pxe_boot_menu_setting
) &&
345 ( ! ( ( pxe_discovery_control
& PXEBS_SKIP
) &&
346 setting_exists ( NULL
, &filename_setting
) ) ) );
350 * Boot from a network device
352 * @v netdev Network device
353 * @ret rc Return status code
355 int netboot ( struct net_device
*netdev
) {
356 struct uri
*filename
;
357 struct uri
*root_path
;
360 /* Close all other network devices */
363 /* Open device and display device status */
364 if ( ( rc
= ifopen ( netdev
) ) != 0 )
368 /* Configure device */
369 if ( ( rc
= ifconf ( netdev
, NULL
) ) != 0 )
373 /* Try PXE menu boot, if applicable */
374 if ( have_pxe_menu() ) {
375 printf ( "Booting from PXE menu\n" );
376 rc
= pxe_menu_boot ( netdev
);
377 goto err_pxe_menu_boot
;
380 /* Fetch next server and filename */
381 filename
= fetch_next_server_and_filename ( NULL
);
384 if ( ! uri_has_path ( filename
) ) {
385 /* Ignore empty filename */
386 uri_put ( filename
);
390 /* Fetch root path */
391 root_path
= fetch_root_path ( NULL
);
394 if ( ! uri_is_absolute ( root_path
) ) {
395 /* Ignore empty root path */
396 uri_put ( root_path
);
400 /* If we have both a filename and a root path, ignore an
401 * unsupported URI scheme in the root path, since it may
402 * represent an NFS root.
404 if ( filename
&& root_path
&&
405 ( xfer_uri_opener ( root_path
->scheme
) == NULL
) ) {
406 printf ( "Ignoring unsupported root path\n" );
407 uri_put ( root_path
);
411 /* Check that we have something to boot */
412 if ( ! ( filename
|| root_path
) ) {
414 printf ( "Nothing to boot: %s\n", strerror ( rc
) );
418 /* Boot using next server, filename and root path */
419 if ( ( rc
= uriboot ( filename
, root_path
, san_default_drive(),
420 ( root_path ?
0 : URIBOOT_NO_SAN
) ) ) != 0 )
425 uri_put ( root_path
);
427 uri_put ( filename
);
436 * Test if network device matches the autoboot device bus type and location
438 * @v netdev Network device
439 * @ret is_autoboot Network device matches the autoboot device
441 static int is_autoboot_busloc ( struct net_device
*netdev
) {
444 for ( dev
= netdev
->dev
; dev
; dev
= dev
->parent
) {
445 if ( ( dev
->desc
.bus_type
== autoboot_desc
.bus_type
) &&
446 ( dev
->desc
.location
== autoboot_desc
.location
) )
453 * Identify autoboot device by bus type and location
455 * @v bus_type Bus type
456 * @v location Location
458 void set_autoboot_busloc ( unsigned int bus_type
, unsigned int location
) {
460 /* Record autoboot device description */
461 autoboot_desc
.bus_type
= bus_type
;
462 autoboot_desc
.location
= location
;
464 /* Mark autoboot device as present */
465 is_autoboot_device
= is_autoboot_busloc
;
469 * Test if network device matches the autoboot device link-layer address
471 * @v netdev Network device
472 * @ret is_autoboot Network device matches the autoboot device
474 static int is_autoboot_ll_addr ( struct net_device
*netdev
) {
476 return ( memcmp ( netdev
->ll_addr
, autoboot_ll_addr
,
477 netdev
->ll_protocol
->ll_addr_len
) == 0 );
481 * Identify autoboot device by link-layer address
483 * @v ll_addr Link-layer address
484 * @v len Length of link-layer address
486 void set_autoboot_ll_addr ( const void *ll_addr
, size_t len
) {
488 /* Record autoboot link-layer address (truncated if necessary) */
489 if ( len
> sizeof ( autoboot_ll_addr
) )
490 len
= sizeof ( autoboot_ll_addr
);
491 memcpy ( autoboot_ll_addr
, ll_addr
, len
);
493 /* Mark autoboot device as present */
494 is_autoboot_device
= is_autoboot_ll_addr
;
500 static int autoboot ( void ) {
501 struct net_device
*netdev
;
504 /* Try booting from each network device. If we have a
505 * specified autoboot device location, then use only devices
506 * matching that location.
508 for_each_netdev ( netdev
) {
510 /* Skip any non-matching devices, if applicable */
511 if ( is_autoboot_device
&& ( ! is_autoboot_device ( netdev
) ) )
514 /* Attempt booting from this device */
515 rc
= netboot ( netdev
);
518 printf ( "No more network devices\n" );
523 * Prompt for shell entry
525 * @ret enter_shell User wants to enter shell
527 static int shell_banner ( void ) {
529 /* Skip prompt if timeout is zero */
530 if ( BANNER_TIMEOUT
<= 0 )
535 return ( prompt ( "Press Ctrl-B for the " PRODUCT_SHORT_NAME
537 ( ( BANNER_TIMEOUT
* TICKS_PER_SEC
) / 10 ),
542 * Main iPXE flow of execution
544 * @v netdev Network device, or NULL
546 void ipxe ( struct net_device
*netdev
) {
547 struct feature
*feature
;
552 * Print welcome banner
555 * If you wish to brand this build of iPXE, please do so by
556 * defining the string PRODUCT_NAME in config/branding.h.
558 * While nothing in the GPL prevents you from removing all
559 * references to iPXE or http://ipxe.org, we prefer you not to
563 printf ( NORMAL
"\n\n" PRODUCT_NAME
"\n" BOLD PRODUCT_SHORT_NAME
" %s"
564 NORMAL
" -- " PRODUCT_TAG_LINE
" -- "
565 CYAN PRODUCT_URI NORMAL
"\nFeatures:", product_version
);
566 for_each_table_entry ( feature
, FEATURES
)
567 printf ( " %s", feature
->name
);
571 if ( ( image
= first_image() ) != NULL
) {
572 /* We have an embedded image; execute it */
573 image_exec ( image
);
574 } else if ( shell_banner() ) {
575 /* User wants shell; just give them a shell */
578 fetch_string_setting_copy ( NULL
, &scriptlet_setting
,
581 /* User has defined a scriptlet; execute it */
582 system ( scriptlet
);
585 /* Try booting. If booting fails, offer the
586 * user another chance to enter the shell.
593 if ( shell_banner() )