|
@@ -49,8 +49,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
49
|
49
|
*
|
50
|
50
|
*/
|
51
|
51
|
|
52
|
|
-/** Device location of preferred autoboot device */
|
53
|
|
-struct device_description autoboot_device;
|
|
52
|
+/** Link-layer address of preferred autoboot device, if known */
|
|
53
|
+static uint8_t autoboot_ll_addr[MAX_LL_ADDR_LEN];
|
|
54
|
+
|
|
55
|
+/** Device location of preferred autoboot device, if known */
|
|
56
|
+static struct device_description autoboot_desc;
|
|
57
|
+
|
|
58
|
+/** Autoboot device tester */
|
|
59
|
+static int ( * is_autoboot_device ) ( struct net_device *netdev );
|
54
|
60
|
|
55
|
61
|
/* Disambiguate the various error causes */
|
56
|
62
|
#define ENOENT_BOOT __einfo_error ( EINFO_ENOENT_BOOT )
|
|
@@ -422,15 +428,60 @@ int netboot ( struct net_device *netdev ) {
|
422
|
428
|
}
|
423
|
429
|
|
424
|
430
|
/**
|
425
|
|
- * Test if network device matches the autoboot device location
|
|
431
|
+ * Test if network device matches the autoboot device bus type and location
|
426
|
432
|
*
|
427
|
433
|
* @v netdev Network device
|
428
|
|
- * @ret is_autoboot Network device matches the autoboot device location
|
|
434
|
+ * @ret is_autoboot Network device matches the autoboot device
|
|
435
|
+ */
|
|
436
|
+static int is_autoboot_busloc ( struct net_device *netdev ) {
|
|
437
|
+
|
|
438
|
+ return ( ( netdev->dev->desc.bus_type == autoboot_desc.bus_type ) &&
|
|
439
|
+ ( netdev->dev->desc.location == autoboot_desc.location ) );
|
|
440
|
+}
|
|
441
|
+
|
|
442
|
+/**
|
|
443
|
+ * Identify autoboot device by bus type and location
|
|
444
|
+ *
|
|
445
|
+ * @v bus_type Bus type
|
|
446
|
+ * @v location Location
|
429
|
447
|
*/
|
430
|
|
-static int is_autoboot_device ( struct net_device *netdev ) {
|
|
448
|
+void set_autoboot_busloc ( unsigned int bus_type, unsigned int location ) {
|
|
449
|
+
|
|
450
|
+ /* Record autoboot device description */
|
|
451
|
+ autoboot_desc.bus_type = bus_type;
|
|
452
|
+ autoboot_desc.location = location;
|
|
453
|
+
|
|
454
|
+ /* Mark autoboot device as present */
|
|
455
|
+ is_autoboot_device = is_autoboot_busloc;
|
|
456
|
+}
|
|
457
|
+
|
|
458
|
+/**
|
|
459
|
+ * Test if network device matches the autoboot device link-layer address
|
|
460
|
+ *
|
|
461
|
+ * @v netdev Network device
|
|
462
|
+ * @ret is_autoboot Network device matches the autoboot device
|
|
463
|
+ */
|
|
464
|
+static int is_autoboot_ll_addr ( struct net_device *netdev ) {
|
|
465
|
+
|
|
466
|
+ return ( memcmp ( netdev->ll_addr, autoboot_ll_addr,
|
|
467
|
+ netdev->ll_protocol->ll_addr_len ) == 0 );
|
|
468
|
+}
|
|
469
|
+
|
|
470
|
+/**
|
|
471
|
+ * Identify autoboot device by link-layer address
|
|
472
|
+ *
|
|
473
|
+ * @v ll_addr Link-layer address
|
|
474
|
+ * @v len Length of link-layer address
|
|
475
|
+ */
|
|
476
|
+void set_autoboot_ll_addr ( const void *ll_addr, size_t len ) {
|
|
477
|
+
|
|
478
|
+ /* Record autoboot link-layer address (truncated if necessary) */
|
|
479
|
+ if ( len > sizeof ( autoboot_ll_addr ) )
|
|
480
|
+ len = sizeof ( autoboot_ll_addr );
|
|
481
|
+ memcpy ( autoboot_ll_addr, ll_addr, len );
|
431
|
482
|
|
432
|
|
- return ( ( netdev->dev->desc.bus_type == autoboot_device.bus_type ) &&
|
433
|
|
- ( netdev->dev->desc.location == autoboot_device.location ) );
|
|
483
|
+ /* Mark autoboot device as present */
|
|
484
|
+ is_autoboot_device = is_autoboot_ll_addr;
|
434
|
485
|
}
|
435
|
486
|
|
436
|
487
|
/**
|
|
@@ -447,8 +498,7 @@ static int autoboot ( void ) {
|
447
|
498
|
for_each_netdev ( netdev ) {
|
448
|
499
|
|
449
|
500
|
/* Skip any non-matching devices, if applicable */
|
450
|
|
- if ( autoboot_device.bus_type &&
|
451
|
|
- ( ! is_autoboot_device ( netdev ) ) )
|
|
501
|
+ if ( is_autoboot_device && ( ! is_autoboot_device ( netdev ) ) )
|
452
|
502
|
continue;
|
453
|
503
|
|
454
|
504
|
/* Attempt booting from this device */
|