Home | History | Annotate | Download | only in efi
      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 
     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 },
     16 };
     17 
     18 /**
     19  * Network stack-specific initialization
     20  */
     21 void net_core_init(void)
     22 {
     23     http_bake_cookies();
     24 }
     25 
     26 void pxe_init_isr(void) {}
     27 void gpxe_init(void) {}
     28 void pxe_idle_init(void) {}
     29 
     30 int reset_pxe(void)
     31 {
     32     return 0;
     33 }
     34 
     35 #define DNS_MAX_SERVERS 4		/* Max no of DNS servers */
     36 uint32_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 
     51 int 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 
     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)));
     78 
     79 struct 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 
     90 void 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