From 0efe1bcf5c2ce89d7c2467550e2823d7f95733e0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 6 May 2016 21:01:01 +0200 Subject: efi_loader: Add network access support We can now successfully boot EFI applications from disk, but users may want to also run them from a PXE setup. This patch implements rudimentary network support, allowing a payload to send and receive network packets. With this patch, I was able to successfully run grub2 with network access inside of QEMU's -M xlnx-ep108. Signed-off-by: Alexander Graf --- include/efi_api.h | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/efi_loader.h | 7 +++ include/net.h | 2 +- 3 files changed, 127 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index 51d7586..20035d7 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -412,4 +412,123 @@ struct efi_gop struct efi_gop_mode *mode; }; +#define EFI_SIMPLE_NETWORK_GUID \ + EFI_GUID(0xa19832b9, 0xac25, 0x11d3, \ + 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +struct efi_mac_address { + char mac_addr[32]; +}; + +struct efi_ip_address { + u8 ip_addr[16]; +}; + +enum efi_simple_network_state { + EFI_NETWORK_STOPPED, + EFI_NETWORK_STARTED, + EFI_NETWORK_INITIALIZED, +}; + +struct efi_simple_network_mode { + enum efi_simple_network_state state; + u32 hwaddr_size; + u32 media_header_size; + u32 max_packet_size; + u32 nvram_size; + u32 nvram_access_size; + u32 receive_filter_mask; + u32 receive_filter_setting; + u32 max_mcast_filter_count; + u32 mcast_filter_count; + struct efi_mac_address mcast_filter[16]; + struct efi_mac_address current_address; + struct efi_mac_address broadcast_address; + struct efi_mac_address permanent_address; + u8 if_type; + u8 mac_changeable; + u8 multitx_supported; + u8 media_present_supported; + u8 media_present; +}; + +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01, +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02, +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04, +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08, +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10, + +struct efi_simple_network +{ + u64 revision; + efi_status_t (EFIAPI *start)(struct efi_simple_network *this); + efi_status_t (EFIAPI *stop)(struct efi_simple_network *this); + efi_status_t (EFIAPI *initialize)(struct efi_simple_network *this, + ulong extra_rx, ulong extra_tx); + efi_status_t (EFIAPI *reset)(struct efi_simple_network *this, + int extended_verification); + efi_status_t (EFIAPI *shutdown)(struct efi_simple_network *this); + efi_status_t (EFIAPI *receive_filters)(struct efi_simple_network *this, + u32 enable, u32 disable, int reset_mcast_filter, + ulong mcast_filter_count, + struct efi_mac_address *mcast_filter); + efi_status_t (EFIAPI *station_address)(struct efi_simple_network *this, + int reset, struct efi_mac_address *new_mac); + efi_status_t (EFIAPI *statistics)(struct efi_simple_network *this, + int reset, ulong *stat_size, void *stat_table); + efi_status_t (EFIAPI *mcastiptomac)(struct efi_simple_network *this, + int ipv6, struct efi_ip_address *ip, + struct efi_mac_address *mac); + efi_status_t (EFIAPI *nvdata)(struct efi_simple_network *this, + int read_write, ulong offset, ulong buffer_size, + char *buffer); + efi_status_t (EFIAPI *get_status)(struct efi_simple_network *this, + u32 *int_status, void **txbuf); + efi_status_t (EFIAPI *transmit)(struct efi_simple_network *this, + ulong header_size, ulong buffer_size, void *buffer, + struct efi_mac_address *src_addr, + struct efi_mac_address *dest_addr, u16 *protocol); + efi_status_t (EFIAPI *receive)(struct efi_simple_network *this, + ulong *header_size, ulong *buffer_size, void *buffer, + struct efi_mac_address *src_addr, + struct efi_mac_address *dest_addr, u16 *protocol); + void (EFIAPI *waitforpacket)(void); + struct efi_simple_network_mode *mode; +}; + +#define EFI_PXE_GUID \ + EFI_GUID(0x03c4e603, 0xac28, 0x11d3, \ + 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +struct efi_pxe_packet { + u8 packet[1472]; +}; + +struct efi_pxe_mode +{ + u8 unused[52]; + struct efi_pxe_packet dhcp_discover; + struct efi_pxe_packet dhcp_ack; + struct efi_pxe_packet proxy_offer; + struct efi_pxe_packet pxe_discover; + struct efi_pxe_packet pxe_reply; +}; + +struct efi_pxe { + u64 rev; + void (EFIAPI *start)(void); + void (EFIAPI *stop)(void); + void (EFIAPI *dhcp)(void); + void (EFIAPI *discover)(void); + void (EFIAPI *mftp)(void); + void (EFIAPI *udpwrite)(void); + void (EFIAPI *udpread)(void); + void (EFIAPI *setipfilter)(void); + void (EFIAPI *arp)(void); + void (EFIAPI *setparams)(void); + void (EFIAPI *setstationip)(void); + void (EFIAPI *setpackets)(void); + struct efi_pxe_mode *mode; +}; + #endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 88b8149..8005454 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -91,6 +91,12 @@ extern struct list_head efi_obj_list; int efi_disk_register(void); /* Called by bootefi to make GOP (graphical) interface available */ int efi_gop_register(void); +/* Called by bootefi to make the network interface available */ +int efi_net_register(void **handle); + +/* Called by networking code to memorize the dhcp ack package */ +void efi_net_set_dhcp_ack(void *pkt, int len); + /* * Stub implementation for a protocol opener that just returns the handle as * interface @@ -157,5 +163,6 @@ static inline void ascii2unicode(u16 *unicode, char *ascii) static inline void efi_restore_gd(void) { } static inline void efi_set_bootdev(const char *dev, const char *devnr, const char *path) { } +static inline void efi_net_set_dhcp_ack(void *pkt, int len) { } #endif diff --git a/include/net.h b/include/net.h index 05800c4..5ee5929 100644 --- a/include/net.h +++ b/include/net.h @@ -269,7 +269,7 @@ int eth_getenv_enetaddr_by_index(const char *base_name, int index, int eth_init(void); /* Initialize the device */ int eth_send(void *packet, int length); /* Send a packet */ -#ifdef CONFIG_API +#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) int eth_receive(void *packet, int length); /* Receive a packet*/ extern void (*push_packet)(void *packet, int length); #endif -- cgit v1.1