1 1.2 rin /* $NetBSD: efipxe.c,v 1.2 2023/07/24 08:30:42 rin Exp $ */ 2 1.1 nonaka /* $OpenBSD: efipxe.c,v 1.3 2018/01/30 20:19:06 naddy Exp $ */ 3 1.1 nonaka 4 1.1 nonaka /* 5 1.1 nonaka * Copyright (c) 2017 Patrick Wildt <patrick (at) blueri.se> 6 1.1 nonaka * 7 1.1 nonaka * Permission to use, copy, modify, and distribute this software for any 8 1.1 nonaka * purpose with or without fee is hereby granted, provided that the above 9 1.1 nonaka * copyright notice and this permission notice appear in all copies. 10 1.1 nonaka * 11 1.1 nonaka * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 1.1 nonaka * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 1.1 nonaka * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 1.1 nonaka * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 1.1 nonaka * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 1.1 nonaka * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 1.1 nonaka * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 1.1 nonaka */ 19 1.1 nonaka 20 1.1 nonaka #include <sys/queue.h> 21 1.1 nonaka 22 1.1 nonaka #include "efiboot.h" 23 1.1 nonaka 24 1.1 nonaka #include <netinet/in.h> 25 1.1 nonaka #include <netinet/in_systm.h> 26 1.1 nonaka #include <lib/libsa/bootp.h> /* for VM_RFC1048 */ 27 1.1 nonaka 28 1.1 nonaka 29 1.1 nonaka struct efipxeinfo { 30 1.1 nonaka TAILQ_ENTRY(efipxeinfo) list; 31 1.1 nonaka 32 1.1 nonaka EFI_PXE_BASE_CODE *pxe; 33 1.1 nonaka EFI_SIMPLE_NETWORK *net; 34 1.1 nonaka EFI_MAC_ADDRESS mac; 35 1.1 nonaka UINT32 addrsz; 36 1.1 nonaka }; 37 1.1 nonaka TAILQ_HEAD(efipxeinfo_lh, efipxeinfo); 38 1.1 nonaka static struct efipxeinfo_lh efi_pxelist; 39 1.1 nonaka static int nefipxes; 40 1.1 nonaka 41 1.1 nonaka void 42 1.1 nonaka efi_pxe_probe(void) 43 1.1 nonaka { 44 1.1 nonaka struct efipxeinfo *epi; 45 1.1 nonaka EFI_PXE_BASE_CODE *pxe; 46 1.1 nonaka EFI_DEVICE_PATH *dp; 47 1.1 nonaka EFI_SIMPLE_NETWORK *net; 48 1.1 nonaka EFI_HANDLE *handles; 49 1.1 nonaka EFI_STATUS status; 50 1.1 nonaka UINTN nhandles; 51 1.1 nonaka int i, depth; 52 1.1 nonaka bool found; 53 1.1 nonaka 54 1.1 nonaka TAILQ_INIT(&efi_pxelist); 55 1.1 nonaka 56 1.1 nonaka status = LibLocateHandle(ByProtocol, &PxeBaseCodeProtocol, NULL, 57 1.1 nonaka &nhandles, &handles); 58 1.1 nonaka if (EFI_ERROR(status)) 59 1.1 nonaka return; 60 1.1 nonaka 61 1.1 nonaka for (i = 0; i < nhandles; i++) { 62 1.1 nonaka status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], 63 1.1 nonaka &DevicePathProtocol, (void **)&dp); 64 1.1 nonaka if (EFI_ERROR(status)) 65 1.1 nonaka continue; 66 1.1 nonaka 67 1.2 rin depth = efi_device_path_depth(efi_bootdp, 68 1.2 rin MESSAGING_DEVICE_PATH); 69 1.1 nonaka if (efi_device_path_ncmp(efi_bootdp, dp, depth)) 70 1.1 nonaka continue; 71 1.1 nonaka 72 1.1 nonaka status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], 73 1.1 nonaka &PxeBaseCodeProtocol, (void **)&pxe); 74 1.1 nonaka if (EFI_ERROR(status)) 75 1.1 nonaka continue; 76 1.1 nonaka 77 1.1 nonaka if (pxe->Mode == NULL || 78 1.1 nonaka (!pxe->Mode->DhcpAckReceived && !pxe->Mode->PxeReplyReceived)) 79 1.1 nonaka continue; 80 1.1 nonaka 81 1.1 nonaka status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], 82 1.1 nonaka &SimpleNetworkProtocol, (void **)&net); 83 1.1 nonaka if (EFI_ERROR(status)) 84 1.1 nonaka continue; 85 1.1 nonaka 86 1.1 nonaka if (net->Mode == NULL) 87 1.1 nonaka continue; 88 1.1 nonaka 89 1.1 nonaka found = false; 90 1.1 nonaka TAILQ_FOREACH(epi, &efi_pxelist, list) { 91 1.1 nonaka if (net->Mode->HwAddressSize == epi->addrsz && 92 1.1 nonaka memcmp(net->Mode->CurrentAddress.Addr, epi->mac.Addr, 93 1.1 nonaka net->Mode->HwAddressSize) == 0) { 94 1.1 nonaka found = true; 95 1.1 nonaka break; 96 1.1 nonaka } 97 1.1 nonaka } 98 1.1 nonaka if (found) 99 1.1 nonaka continue; 100 1.1 nonaka 101 1.1 nonaka epi = alloc(sizeof(*epi)); 102 1.1 nonaka if (epi == NULL) 103 1.1 nonaka continue; 104 1.1 nonaka 105 1.1 nonaka memset(epi, 0, sizeof(*epi)); 106 1.1 nonaka epi->pxe = pxe; 107 1.1 nonaka epi->net = net; 108 1.1 nonaka epi->addrsz = net->Mode->HwAddressSize; 109 1.1 nonaka memcpy(epi->mac.Addr, net->Mode->CurrentAddress.Addr, epi->addrsz); 110 1.1 nonaka 111 1.1 nonaka TAILQ_INSERT_TAIL(&efi_pxelist, epi, list); 112 1.1 nonaka nefipxes++; 113 1.1 nonaka } 114 1.1 nonaka } 115 1.1 nonaka 116 1.1 nonaka void 117 1.1 nonaka efi_pxe_show(void) 118 1.1 nonaka { 119 1.1 nonaka const struct efipxeinfo *epi; 120 1.1 nonaka UINT32 i, n; 121 1.1 nonaka 122 1.1 nonaka n = 0; 123 1.1 nonaka TAILQ_FOREACH(epi, &efi_pxelist, list) { 124 1.1 nonaka printf("pxe pxe%d", n++); 125 1.1 nonaka for (i = 0; i < epi->addrsz; i++) 126 1.1 nonaka printf("%c%02x", i == 0 ? ' ' : ':', epi->mac.Addr[i]); 127 1.1 nonaka printf("\n"); 128 1.1 nonaka } 129 1.1 nonaka } 130 1.1 nonaka 131 1.1 nonaka bool 132 1.1 nonaka efi_pxe_match_booted_interface(const EFI_MAC_ADDRESS *mac, UINT32 addrsz) 133 1.1 nonaka { 134 1.1 nonaka const struct efipxeinfo *epi; 135 1.1 nonaka 136 1.1 nonaka TAILQ_FOREACH(epi, &efi_pxelist, list) { 137 1.1 nonaka if (addrsz == epi->addrsz && 138 1.1 nonaka memcmp(mac->Addr, epi->mac.Addr, addrsz) == 0) 139 1.1 nonaka return true; 140 1.1 nonaka } 141 1.1 nonaka return false; 142 1.1 nonaka } 143