efi/pxe: Use the appropriate 3rd packet
[syslinux.git] / efi / pxe.c
blob0aa6e19e2047490e223e67dfe304e27b3e819048
1 /*
2 * Copyright 2013-2014 Intel Corporation - All Rights Reserved
3 */
5 #include <syslinux/firmware.h>
6 #include <syslinux/pxe_api.h>
7 #include "efi.h"
8 #include "net.h"
9 #include "fs/pxe/pxe.h"
11 const struct url_scheme url_schemes[] = {
12 { "tftp", tftp_open, 0 },
13 { "http", http_open, O_DIRECTORY },
14 { "ftp", ftp_open, O_DIRECTORY },
15 { NULL, NULL, 0 },
18 /**
19 * Network stack-specific initialization
21 void net_core_init(void)
23 http_bake_cookies();
26 void pxe_init_isr(void) {}
27 void gpxe_init(void) {}
28 void pxe_idle_init(void) {}
30 int reset_pxe(void)
32 return 0;
35 #define DNS_MAX_SERVERS 4 /* Max no of DNS servers */
36 uint32_t dns_server[DNS_MAX_SERVERS] = {0, };
38 __export uint32_t dns_resolv(const char *name)
41 * Return failure on an empty input... this can happen during
42 * some types of URL parsing, and this is the easiest place to
43 * check for it.
45 if (!name || !*name)
46 return 0;
48 return 0;
51 int pxe_init(bool quiet)
53 EFI_HANDLE *handles;
54 EFI_STATUS status;
55 UINTN nr_handles;
57 status = LibLocateHandle(ByProtocol, &PxeBaseCodeProtocol,
58 NULL, &nr_handles, &handles);
59 if (status != EFI_SUCCESS) {
60 if (!quiet)
61 Print(L"No PXE Base Code Protocol\n");
62 return -1;
65 return 0;
68 #define EDHCP_BUF_LEN 8192
70 struct embedded_dhcp_options {
71 uint32_t magic[4];
72 uint32_t bdhcp_len;
73 uint32_t adhcp_len;
74 uint32_t buffer_size;
75 uint32_t reserved;
76 uint8_t dhcp_data[EDHCP_BUF_LEN];
77 } __attribute__((aligned(16)));
79 struct embedded_dhcp_options embedded_dhcp_options =
81 .magic[0] = 0x2a171ead,
82 .magic[1] = 0x0600e65e,
83 .magic[2] = 0x4025a4e4,
84 .magic[3] = 0x42388fc8,
85 .bdhcp_len = 0,
86 .adhcp_len = 0,
87 .buffer_size = EDHCP_BUF_LEN,
90 void net_parse_dhcp(void)
92 EFI_PXE_BASE_CODE_MODE *mode;
93 EFI_PXE_BASE_CODE *bc;
94 unsigned int pkt_len = sizeof(EFI_PXE_BASE_CODE_PACKET);
95 EFI_STATUS status;
96 EFI_HANDLE *handles = NULL;
97 UINTN nr_handles = 0;
98 uint8_t hardlen;
99 uint32_t ip;
100 char dst[256];
102 status = LibLocateHandle(ByProtocol, &PxeBaseCodeProtocol,
103 NULL, &nr_handles, &handles);
104 if (status != EFI_SUCCESS)
105 return;
107 /* Probably want to use IPv4 protocol to decide which handle to use */
108 status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[0],
109 &PxeBaseCodeProtocol, (void **)&bc);
110 if (status != EFI_SUCCESS) {
111 Print(L"Failed to lookup PxeBaseCodeProtocol\n");
114 mode = bc->Mode;
117 * Parse any "before" hardcoded options
119 parse_dhcp_options(embedded_dhcp_options.dhcp_data,
120 embedded_dhcp_options.bdhcp_len, 0);
123 * Get the DHCP client identifiers (BIOS/PXE query info 1)
125 Print(L"Getting cached packet ");
126 parse_dhcp(&mode->DhcpDiscover.Dhcpv4, pkt_len);
128 * We don't use flags from the request packet, so
129 * this is a good time to initialize DHCPMagic...
130 * Initialize it to 1 meaning we will accept options found;
131 * in earlier versions of PXELINUX bit 0 was used to indicate
132 * we have found option 208 with the appropriate magic number;
133 * we no longer require that, but MAY want to re-introduce
134 * it in the future for vendor encapsulated options.
136 *(char *)&DHCPMagic = 1;
139 * Get the BOOTP/DHCP packet that brought us file (and an IP
140 * address). This lives in the DHCPACK packet (BIOS/PXE query info 2)
142 parse_dhcp(&mode->DhcpAck.Dhcpv4, pkt_len);
144 * Save away MAC address (assume this is in query info 2. If this
145 * turns out to be problematic it might be better getting it from
146 * the query info 1 packet
148 hardlen = mode->DhcpAck.Dhcpv4.BootpHwAddrLen;
149 MAC_len = hardlen > 16 ? 0 : hardlen;
150 MAC_type = mode->DhcpAck.Dhcpv4.BootpHwType;
151 memcpy(MAC, mode->DhcpAck.Dhcpv4.BootpHwAddr, MAC_len);
154 * Get the boot file and other info. This lives in the CACHED_REPLY
155 * packet (BIOS/PXE query info 3)
157 EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = NULL;
159 if (mode->PxeReplyReceived)
160 pkt_v4 = &mode->PxeReply.Dhcpv4;
161 else if (mode->ProxyOfferReceived)
162 pkt_v4 = &mode->ProxyOffer.Dhcpv4;
164 if (pkt_v4)
165 parse_dhcp(pkt_v4, pkt_len);
166 Print(L"\n");
169 * Parse any "after" hardcoded options
171 parse_dhcp_options(embedded_dhcp_options.dhcp_data +
172 embedded_dhcp_options.bdhcp_len,
173 embedded_dhcp_options.adhcp_len, 0);
175 ip = IPInfo.myip;
176 sprintf(dst, "%u.%u.%u.%u",
177 ((const uint8_t *)&ip)[0],
178 ((const uint8_t *)&ip)[1],
179 ((const uint8_t *)&ip)[2],
180 ((const uint8_t *)&ip)[3]);
182 Print(L"My IP is %a\n", dst);