1/* 2 * Copyright 2013-2014 Intel Corporation - All Rights Reserved 3 */ 4 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" 10 11const 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 }, 16}; 17 18/** 19 * Network stack-specific initialization 20 */ 21void net_core_init(void) 22{ 23 http_bake_cookies(); 24} 25 26void pxe_init_isr(void) {} 27void gpxe_init(void) {} 28void pxe_idle_init(void) {} 29 30int reset_pxe(void) 31{ 32 return 0; 33} 34 35#define DNS_MAX_SERVERS 4 /* Max no of DNS servers */ 36uint32_t dns_server[DNS_MAX_SERVERS] = {0, }; 37 38__export uint32_t dns_resolv(const char *name) 39{ 40 /* 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. 44 */ 45 if (!name || !*name) 46 return 0; 47 48 return 0; 49} 50 51int pxe_init(bool quiet) 52{ 53 EFI_HANDLE *handles; 54 EFI_STATUS status; 55 UINTN nr_handles; 56 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; 63 } 64 65 return 0; 66} 67 68#define EDHCP_BUF_LEN 8192 69 70struct 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))); 78 79struct embedded_dhcp_options embedded_dhcp_options = 80{ 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, 88}; 89 90void net_parse_dhcp(void) 91{ 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]; 101 102 status = LibLocateHandle(ByProtocol, &PxeBaseCodeProtocol, 103 NULL, &nr_handles, &handles); 104 if (status != EFI_SUCCESS) 105 return; 106 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"); 112 } 113 114 mode = bc->Mode; 115 116 /* 117 * Parse any "before" hardcoded options 118 */ 119 parse_dhcp_options(embedded_dhcp_options.dhcp_data, 120 embedded_dhcp_options.bdhcp_len, 0); 121 122 /* 123 * Get the DHCP client identifiers (query info 1) 124 */ 125 Print(L"Getting cached packet "); 126 parse_dhcp(&mode->DhcpDiscover.Dhcpv4, pkt_len); 127 /* 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. 135 */ 136 *(char *)&DHCPMagic = 1; 137 138 /* 139 * Get the BOOTP/DHCP packet that brought us file (and an IP 140 * address). This lives in the DHCPACK packet (query info 2) 141 */ 142 parse_dhcp(&mode->DhcpAck.Dhcpv4, pkt_len); 143 /* 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 147 */ 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); 152 153 /* 154 * Get the boot file and other info. This lives in the CACHED_REPLY 155 * packet (query info 3) 156 */ 157 parse_dhcp(&mode->PxeReply.Dhcpv4, pkt_len); 158 Print(L"\n"); 159 160 /* 161 * Parse any "after" hardcoded options 162 */ 163 parse_dhcp_options(embedded_dhcp_options.dhcp_data + 164 embedded_dhcp_options.bdhcp_len, 165 embedded_dhcp_options.adhcp_len, 0); 166 167 ip = IPInfo.myip; 168 sprintf(dst, "%u.%u.%u.%u", 169 ((const uint8_t *)&ip)[0], 170 ((const uint8_t *)&ip)[1], 171 ((const uint8_t *)&ip)[2], 172 ((const uint8_t *)&ip)[3]); 173 174 Print(L"My IP is %a\n", dst); 175} 176