autoboot.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include <errno.h>
00024 #include <gpxe/netdevice.h>
00025 #include <gpxe/dhcp.h>
00026 #include <gpxe/settings.h>
00027 #include <gpxe/image.h>
00028 #include <gpxe/sanboot.h>
00029 #include <gpxe/uri.h>
00030 #include <usr/ifmgmt.h>
00031 #include <usr/route.h>
00032 #include <usr/dhcpmgmt.h>
00033 #include <usr/imgmgmt.h>
00034 #include <usr/autoboot.h>
00035
00036
00037
00038
00039
00040
00041
00042
00043 int shutdown_exit_flags = 0;
00044
00045
00046
00047
00048
00049
00050 static struct net_device * find_boot_netdev ( void ) {
00051 return NULL;
00052 }
00053
00054
00055
00056
00057
00058
00059
00060 int boot_next_server_and_filename ( struct in_addr next_server,
00061 const char *filename ) {
00062 struct uri *uri;
00063 struct image *image;
00064 char buf[ 23 +
00065 ( 3 * strlen(filename) )
00066 + 1 ];
00067 int filename_is_absolute;
00068 int rc;
00069
00070
00071 uri = parse_uri ( filename );
00072 if ( ! uri )
00073 return -ENOMEM;
00074 filename_is_absolute = uri_is_absolute ( uri );
00075 uri_put ( uri );
00076 if ( ! filename_is_absolute ) {
00077
00078
00079
00080
00081
00082
00083 snprintf ( buf, sizeof ( buf ), "tftp://%s/",
00084 inet_ntoa ( next_server ) );
00085 uri_encode ( filename, buf + strlen ( buf ),
00086 sizeof ( buf ) - strlen ( buf ), URI_PATH );
00087 filename = buf;
00088 }
00089
00090 image = alloc_image();
00091 if ( ! image )
00092 return -ENOMEM;
00093 if ( ( rc = imgfetch ( image, filename,
00094 register_and_autoload_image ) ) != 0 ) {
00095 goto done;
00096 }
00097 if ( ( rc = imgexec ( image ) ) != 0 )
00098 goto done;
00099
00100 done:
00101 image_put ( image );
00102 return rc;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111 int boot_root_path ( const char *root_path ) {
00112 struct sanboot_protocol *sanboot;
00113
00114
00115 for_each_table_entry ( sanboot, SANBOOT_PROTOCOLS ) {
00116 if ( strncmp ( root_path, sanboot->prefix,
00117 strlen ( sanboot->prefix ) ) == 0 ) {
00118 return sanboot->boot ( root_path );
00119 }
00120 }
00121
00122 return -ENOTSUP;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 static int netboot ( struct net_device *netdev ) {
00132 struct setting vendor_class_id_setting
00133 = { .tag = DHCP_VENDOR_CLASS_ID };
00134 struct setting pxe_discovery_control_setting
00135 = { .tag = DHCP_PXE_DISCOVERY_CONTROL };
00136 struct setting pxe_boot_menu_setting
00137 = { .tag = DHCP_PXE_BOOT_MENU };
00138 char buf[256];
00139 struct in_addr next_server;
00140 unsigned int pxe_discovery_control;
00141 int rc;
00142
00143
00144 if ( ( rc = ifopen ( netdev ) ) != 0 )
00145 return rc;
00146 ifstat ( netdev );
00147
00148
00149 if ( ( rc = dhcp ( netdev ) ) != 0 )
00150 return rc;
00151 route();
00152
00153
00154 fetch_string_setting ( NULL, &vendor_class_id_setting,
00155 buf, sizeof ( buf ) );
00156 pxe_discovery_control =
00157 fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
00158 if ( ( strcmp ( buf, "PXEClient" ) == 0 ) && pxe_menu_boot != NULL &&
00159 setting_exists ( NULL, &pxe_boot_menu_setting ) &&
00160 ( ! ( ( pxe_discovery_control & PXEBS_SKIP ) &&
00161 setting_exists ( NULL, &filename_setting ) ) ) ) {
00162 printf ( "Booting from PXE menu\n" );
00163 return pxe_menu_boot ( netdev );
00164 }
00165
00166
00167 fetch_ipv4_setting ( NULL, &next_server_setting, &next_server );
00168 fetch_string_setting ( NULL, &filename_setting, buf, sizeof ( buf ) );
00169 if ( buf[0] ) {
00170 printf ( "Booting from filename \"%s\"\n", buf );
00171 if ( ( rc = boot_next_server_and_filename ( next_server,
00172 buf ) ) != 0 ) {
00173 printf ( "Could not boot from filename \"%s\": %s\n",
00174 buf, strerror ( rc ) );
00175 return rc;
00176 }
00177 return 0;
00178 }
00179
00180
00181 fetch_string_setting ( NULL, &root_path_setting, buf, sizeof ( buf ) );
00182 if ( buf[0] ) {
00183 printf ( "Booting from root path \"%s\"\n", buf );
00184 if ( ( rc = boot_root_path ( buf ) ) != 0 ) {
00185 printf ( "Could not boot from root path \"%s\": %s\n",
00186 buf, strerror ( rc ) );
00187 return rc;
00188 }
00189 return 0;
00190 }
00191
00192 printf ( "No filename or root path specified\n" );
00193 return -ENOENT;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 static void close_all_netdevs ( void ) {
00205 struct net_device *netdev;
00206
00207 for_each_netdev ( netdev ) {
00208 ifclose ( netdev );
00209 }
00210 }
00211
00212
00213
00214
00215 void autoboot ( void ) {
00216 struct net_device *boot_netdev;
00217 struct net_device *netdev;
00218
00219
00220 close_all_netdevs();
00221 if ( ( boot_netdev = find_boot_netdev() ) )
00222 netboot ( boot_netdev );
00223
00224
00225 for_each_netdev ( netdev ) {
00226 if ( netdev == boot_netdev )
00227 continue;
00228 close_all_netdevs();
00229 netboot ( netdev );
00230 }
00231
00232 printf ( "No more network devices\n" );
00233 }