Mon Jan 1 13:38:57 2024 UTC (140d)
MI efiboot: Revert "Stop using efi_bootdp after exclusive open for PXE"

http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/stand/efiboot/efinet.c#rev1.7

Some UEFI implementations pass multiple boot options as boot device path,
and NULL-clearing it results in boot failures.

Thanks skrll@ for pointing it out.


(rin)
diff -r1.8 -r1.9 src/sys/stand/efiboot/efinet.c

cvs diff -r1.8 -r1.9 src/sys/stand/efiboot/efinet.c (expand / switch to unified diff)

--- src/sys/stand/efiboot/efinet.c 2023/12/27 09:40:35 1.8
+++ src/sys/stand/efiboot/efinet.c 2024/01/01 13:38:57 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: efinet.c,v 1.8 2023/12/27 09:40:35 rin Exp $ */ 1/* $NetBSD: efinet.c,v 1.9 2024/01/01 13:38:57 rin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2001 Doug Rabson 4 * Copyright (c) 2001 Doug Rabson
5 * Copyright (c) 2002, 2006 Marcel Moolenaar 5 * Copyright (c) 2002, 2006 Marcel Moolenaar
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -323,27 +323,27 @@ efinet_end(struct netif *nif) @@ -323,27 +323,27 @@ efinet_end(struct netif *nif)
323 323
324void 324void
325efi_net_probe(void) 325efi_net_probe(void)
326{ 326{
327 struct efinetinfo *enis; 327 struct efinetinfo *enis;
328 struct netif_dif *dif; 328 struct netif_dif *dif;
329 struct netif_stats *stats; 329 struct netif_stats *stats;
330 EFI_DEVICE_PATH *dp0, *dp; 330 EFI_DEVICE_PATH *dp0, *dp;
331 EFI_SIMPLE_NETWORK *net; 331 EFI_SIMPLE_NETWORK *net;
332 EFI_HANDLE *handles; 332 EFI_HANDLE *handles;
333 EFI_STATUS status; 333 EFI_STATUS status;
334 UINTN i, nhandles; 334 UINTN i, nhandles;
335 int nifs, depth = -1; 335 int nifs, depth = -1;
336 bool found, is_bootdp; 336 bool found;
337 337
338 status = LibLocateHandle(ByProtocol, &SimpleNetworkProtocol, NULL, 338 status = LibLocateHandle(ByProtocol, &SimpleNetworkProtocol, NULL,
339 &nhandles, &handles); 339 &nhandles, &handles);
340 if (EFI_ERROR(status) || nhandles == 0) 340 if (EFI_ERROR(status) || nhandles == 0)
341 return; 341 return;
342 342
343 enis = alloc(nhandles * sizeof(*enis)); 343 enis = alloc(nhandles * sizeof(*enis));
344 if (enis == NULL) 344 if (enis == NULL)
345 return; 345 return;
346 memset(enis, 0, nhandles * sizeof(*enis)); 346 memset(enis, 0, nhandles * sizeof(*enis));
347 347
348 if (efi_bootdp) { 348 if (efi_bootdp) {
349 /* 349 /*
@@ -367,29 +367,26 @@ efi_net_probe(void) @@ -367,29 +367,26 @@ efi_net_probe(void)
367 continue; 367 continue;
368 368
369 found = false; 369 found = false;
370 for (dp = dp0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { 370 for (dp = dp0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) {
371 if (DevicePathType(dp) == MESSAGING_DEVICE_PATH && 371 if (DevicePathType(dp) == MESSAGING_DEVICE_PATH &&
372 DevicePathSubType(dp) == MSG_MAC_ADDR_DP) { 372 DevicePathSubType(dp) == MSG_MAC_ADDR_DP) {
373 found = true; 373 found = true;
374 break; 374 break;
375 } 375 }
376 } 376 }
377 if (!found) 377 if (!found)
378 continue; 378 continue;
379 379
380 is_bootdp = depth > 0 && 
381 efi_device_path_ncmp(efi_bootdp, dp0, depth) == 0; 
382 
383 status = uefi_call_wrapper(BS->OpenProtocol, 6, handles[i], 380 status = uefi_call_wrapper(BS->OpenProtocol, 6, handles[i],
384 &SimpleNetworkProtocol, (void **)&net, IH, NULL, 381 &SimpleNetworkProtocol, (void **)&net, IH, NULL,
385 EFI_OPEN_PROTOCOL_EXCLUSIVE); 382 EFI_OPEN_PROTOCOL_EXCLUSIVE);
386 if (EFI_ERROR(status)) { 383 if (EFI_ERROR(status)) {
387 printf("Unable to open network interface %" PRIuMAX 384 printf("Unable to open network interface %" PRIuMAX
388 " for exclusive access: %" PRIxMAX "\n", 385 " for exclusive access: %" PRIxMAX "\n",
389 (uintmax_t)i, (uintmax_t)status); 386 (uintmax_t)i, (uintmax_t)status);
390 continue; 387 continue;
391 } 388 }
392 389
393 enis[nifs].net = net; 390 enis[nifs].net = net;
394 enis[nifs].bootdev = efi_pxe_match_booted_interface( 391 enis[nifs].bootdev = efi_pxe_match_booted_interface(
395 efinet_hwaddr(net->Mode), net->Mode->HwAddressSize); 392 efinet_hwaddr(net->Mode), net->Mode->HwAddressSize);
@@ -397,41 +394,30 @@ efi_net_probe(void) @@ -397,41 +394,30 @@ efi_net_probe(void)
397 ETHER_EXT_LEN; 394 ETHER_EXT_LEN;
398 enis[nifs].pktbuf = alloc(enis[nifs].pktbufsz); 395 enis[nifs].pktbuf = alloc(enis[nifs].pktbufsz);
399 if (enis[nifs].pktbuf == NULL) { 396 if (enis[nifs].pktbuf == NULL) {
400 while (i-- > 0) { 397 while (i-- > 0) {
401 dealloc(enis[i].pktbuf, enis[i].pktbufsz); 398 dealloc(enis[i].pktbuf, enis[i].pktbufsz);
402 if (i == 0) 399 if (i == 0)
403 break; 400 break;
404 } 401 }
405 dealloc(enis, nhandles * sizeof(*enis)); 402 dealloc(enis, nhandles * sizeof(*enis));
406 FreePool(handles); 403 FreePool(handles);
407 return; 404 return;
408 } 405 }
409 406
410 if (is_bootdp) { 407 if (depth > 0 && efi_device_path_ncmp(efi_bootdp, dp0, depth) == 0) {
411 /* 
412 * This is boot device... 
413 */ 
414 char devname[9]; 408 char devname[9];
415 
416 snprintf(devname, sizeof(devname), "net%u", nifs); 409 snprintf(devname, sizeof(devname), "net%u", nifs);
417 set_default_device(devname); 410 set_default_device(devname);
418 
419 /* 
420 * and now opened for us excluively. Therefore, 
421 * access via device path is illegal. 
422 */ 
423 efi_bootdp = NULL; 
424 depth = -1; 
425 } 411 }
426 412
427 nifs++; 413 nifs++;
428 } 414 }
429 415
430 FreePool(handles); 416 FreePool(handles);
431 417
432 if (nifs == 0) 418 if (nifs == 0)
433 return; 419 return;
434 420
435 efinetif.netif_ifs = alloc(nifs * sizeof(*dif)); 421 efinetif.netif_ifs = alloc(nifs * sizeof(*dif));
436 stats = alloc(nifs * sizeof(*stats)); 422 stats = alloc(nifs * sizeof(*stats));
437 if (efinetif.netif_ifs == NULL || stats == NULL) { 423 if (efinetif.netif_ifs == NULL || stats == NULL) {