| 
				
			 | 
			
			
				
				@@ -24,6 +24,7 @@ 
			 | 
		
		
	
		
			
			| 
				24
			 | 
			
				24
			 | 
			
			
				
				 #include <gpxe/settings.h> 
			 | 
		
		
	
		
			
			| 
				25
			 | 
			
				25
			 | 
			
			
				
				 #include <gpxe/image.h> 
			 | 
		
		
	
		
			
			| 
				26
			 | 
			
				26
			 | 
			
			
				
				 #include <gpxe/embedded.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				27
			 | 
			
			
				
				+#include <gpxe/uri.h> 
			 | 
		
		
	
		
			
			| 
				27
			 | 
			
				28
			 | 
			
			
				
				 #include <usr/ifmgmt.h> 
			 | 
		
		
	
		
			
			| 
				28
			 | 
			
				29
			 | 
			
			
				
				 #include <usr/route.h> 
			 | 
		
		
	
		
			
			| 
				29
			 | 
			
				30
			 | 
			
			
				
				 #include <usr/dhcpmgmt.h> 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -78,15 +79,39 @@ static int boot_embedded_image ( void ) { 
			 | 
		
		
	
		
			
			| 
				78
			 | 
			
				79
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				79
			 | 
			
				80
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				80
			 | 
			
				81
			 | 
			
			
				
				 /** 
			 | 
		
		
	
		
			
			| 
				81
			 | 
			
				
			 | 
			
			
				
				- * Boot using filename 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				82
			 | 
			
			
				
				+ * Boot using next-server and filename 
			 | 
		
		
	
		
			
			| 
				82
			 | 
			
				83
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				83
			 | 
			
				84
			 | 
			
			
				
				  * @v filename		Boot filename 
			 | 
		
		
	
		
			
			| 
				84
			 | 
			
				85
			 | 
			
			
				
				  * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				85
			 | 
			
				86
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				86
			 | 
			
				
			 | 
			
			
				
				-static int boot_filename ( const char *filename ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				87
			 | 
			
			
				
				+static int boot_next_server_and_filename ( struct in_addr next_server, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				88
			 | 
			
			
				
				+					   const char *filename ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				89
			 | 
			
			
				
				+	struct uri *uri; 
			 | 
		
		
	
		
			
			| 
				87
			 | 
			
				90
			 | 
			
			
				
				 	struct image *image; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				91
			 | 
			
			
				
				+	char buf[ 23 /* tftp://xxx.xxx.xxx.xxx/ */ + strlen(filename) + 1 ]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				92
			 | 
			
			
				
				+	int filename_is_absolute; 
			 | 
		
		
	
		
			
			| 
				88
			 | 
			
				93
			 | 
			
			
				
				 	int rc; 
			 | 
		
		
	
		
			
			| 
				89
			 | 
			
				94
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				95
			 | 
			
			
				
				+	/* Construct URI */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				96
			 | 
			
			
				
				+	uri = parse_uri ( filename ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				97
			 | 
			
			
				
				+	if ( ! uri ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				98
			 | 
			
			
				
				+		printf ( "Out of memory\n" ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				99
			 | 
			
			
				
				+		return -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				100
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				101
			 | 
			
			
				
				+	filename_is_absolute = uri_is_absolute ( uri ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				102
			 | 
			
			
				
				+	uri_put ( uri ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				103
			 | 
			
			
				
				+	if ( ! filename_is_absolute ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				104
			 | 
			
			
				
				+		/* Construct a tftp:// URI for the filename.  We can't 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				105
			 | 
			
			
				
				+		 * just rely on the current working URI, because the 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				106
			 | 
			
			
				
				+		 * relative URI resolution will remove the distinction 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				107
			 | 
			
			
				
				+		 * between filenames with and without initial slashes, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				108
			 | 
			
			
				
				+		 * which is significant for TFTP. 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				109
			 | 
			
			
				
				+		 */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				110
			 | 
			
			
				
				+		snprintf ( buf, sizeof ( buf ), "tftp://%s/%s", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				111
			 | 
			
			
				
				+			   inet_ntoa ( next_server ), filename ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				112
			 | 
			
			
				
				+		filename = buf; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				113
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				114
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				90
			 | 
			
				115
			 | 
			
			
				
				 	image = alloc_image(); 
			 | 
		
		
	
		
			
			| 
				91
			 | 
			
				116
			 | 
			
			
				
				 	if ( ! image ) { 
			 | 
		
		
	
		
			
			| 
				92
			 | 
			
				117
			 | 
			
			
				
				 		printf ( "Out of memory\n" ); 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -135,6 +160,7 @@ int boot_root_path ( const char *root_path ) { 
			 | 
		
		
	
		
			
			| 
				135
			 | 
			
				160
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				136
			 | 
			
				161
			 | 
			
			
				
				 static int netboot ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				137
			 | 
			
				162
			 | 
			
			
				
				 	char buf[256]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				163
			 | 
			
			
				
				+	struct in_addr next_server; 
			 | 
		
		
	
		
			
			| 
				138
			 | 
			
				164
			 | 
			
			
				
				 	int rc; 
			 | 
		
		
	
		
			
			| 
				139
			 | 
			
				165
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				140
			 | 
			
				166
			 | 
			
			
				
				 	/* Open device and display device status */ 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -161,10 +187,11 @@ static int netboot ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				161
			 | 
			
				187
			 | 
			
			
				
				 		return rc; 
			 | 
		
		
	
		
			
			| 
				162
			 | 
			
				188
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				163
			 | 
			
				189
			 | 
			
			
				
				 	/* Try to download and boot whatever we are given as a filename */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				190
			 | 
			
			
				
				+	fetch_ipv4_setting ( NULL, &next_server_setting, &next_server ); 
			 | 
		
		
	
		
			
			| 
				164
			 | 
			
				191
			 | 
			
			
				
				 	fetch_string_setting ( NULL, &filename_setting, buf, sizeof ( buf ) ); 
			 | 
		
		
	
		
			
			| 
				165
			 | 
			
				192
			 | 
			
			
				
				 	if ( buf[0] ) { 
			 | 
		
		
	
		
			
			| 
				166
			 | 
			
				193
			 | 
			
			
				
				 		printf ( "Booting from filename \"%s\"\n", buf ); 
			 | 
		
		
	
		
			
			| 
				167
			 | 
			
				
			 | 
			
			
				
				-		return boot_filename ( buf ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				194
			 | 
			
			
				
				+		return boot_next_server_and_filename ( next_server, buf ); 
			 | 
		
		
	
		
			
			| 
				168
			 | 
			
				195
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				169
			 | 
			
				196
			 | 
			
			
				
				 	 
			 | 
		
		
	
		
			
			| 
				170
			 | 
			
				197
			 | 
			
			
				
				 	/* No filename; try the root path */ 
			 |