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