diff options
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 13 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 20 | ||||
-rw-r--r-- | lib/efi_loader/efi_net.c | 92 | ||||
-rw-r--r-- | lib/efi_loader/efi_runtime.c | 19 |
4 files changed, 104 insertions, 40 deletions
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index bf78176217..b26ac9fbfc 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -6,18 +6,20 @@ */ #include <common.h> +#include <bootm.h> #include <div64.h> +#include <dm/device.h> +#include <dm/root.h> #include <efi_loader.h> #include <irq_func.h> #include <log.h> #include <malloc.h> -#include <time.h> -#include <linux/libfdt_env.h> -#include <u-boot/crc.h> -#include <bootm.h> #include <pe.h> +#include <time.h> #include <u-boot/crc.h> +#include <usb.h> #include <watchdog.h> +#include <linux/libfdt_env.h> DECLARE_GLOBAL_DATA_PTR; @@ -1994,7 +1996,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, list_del(&evt->link); } + if IS_ENABLED(CONFIG_USB_DEVICE) + udc_disconnect(); board_quiesce_devices(); + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); /* Patch out unsupported runtime function */ efi_runtime_detach(); diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 426de77951..011accab78 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -76,7 +76,7 @@ static int term_get_char(s32 *c) if (timer_get_us() > timeout) return 1; - *c = getc(); + *c = getchar(); return 0; } @@ -269,7 +269,7 @@ static int query_console_serial(int *rows, int *cols) /* Empty input buffer */ while (tstc()) - getc(); + getchar(); /* * Not all terminals understand CSI [18t for querying the console size. @@ -634,13 +634,13 @@ static int analyze_modifiers(struct efi_key_state *key_state) { int c, mod = 0, ret = 0; - c = getc(); + c = getchar(); if (c != ';') { ret = c; if (c == '~') goto out; - c = getc(); + c = getchar(); } for (;;) { switch (c) { @@ -649,7 +649,7 @@ static int analyze_modifiers(struct efi_key_state *key_state) mod += c - '0'; /* fall through */ case ';': - c = getc(); + c = getchar(); break; default: goto out; @@ -692,25 +692,25 @@ static efi_status_t efi_cin_read_key(struct efi_key_data *key) * Xterm Control Sequences * https://www.xfree86.org/4.8.0/ctlseqs.html */ - ch = getc(); + ch = getchar(); switch (ch) { case cESC: /* ESC */ pressed_key.scan_code = 23; break; case 'O': /* F1 - F4, End */ - ch = getc(); + ch = getchar(); /* consider modifiers */ if (ch == 'F') { /* End */ pressed_key.scan_code = 6; break; } else if (ch < 'P') { set_shift_mask(ch - '0', &key->key_state); - ch = getc(); + ch = getchar(); } pressed_key.scan_code = ch - 'P' + 11; break; case '[': - ch = getc(); + ch = getchar(); switch (ch) { case 'A'...'D': /* up, down right, left */ pressed_key.scan_code = ch - 'A' + 1; @@ -868,7 +868,7 @@ static void efi_cin_check(void) static void efi_cin_empty_buffer(void) { while (tstc()) - getc(); + getchar(); key_available = false; } diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 22f0123eca..69276b275d 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -24,9 +24,12 @@ static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; static const efi_guid_t efi_pxe_base_code_protocol_guid = EFI_PXE_BASE_CODE_PROTOCOL_GUID; static struct efi_pxe_packet *dhcp_ack; -static bool new_rx_packet; static void *new_tx_packet; static void *transmit_buffer; +static uchar **receive_buffer; +static size_t *receive_lengths; +static int rx_packet_idx; +static int rx_packet_num; /* * The notification function of this event is called in every timer cycle @@ -115,6 +118,8 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this) } else { /* Disable hardware and put it into the reset state */ eth_halt(); + /* Clear cache of packets */ + rx_packet_num = 0; this->mode->state = EFI_NETWORK_STOPPED; } out: @@ -160,6 +165,8 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, net_init(); /* Disable hardware and put it into the reset state */ eth_halt(); + /* Clear cache of packets */ + rx_packet_num = 0; /* Set current device according to environment variables */ eth_set_current(); /* Get hardware ready for send and receive operations */ @@ -602,16 +609,16 @@ static efi_status_t EFIAPI efi_net_receive break; } - if (!new_rx_packet) { + if (!rx_packet_num) { ret = EFI_NOT_READY; goto out; } /* Fill export parameters */ - eth_hdr = (struct ethernet_hdr *)net_rx_packet; + eth_hdr = (struct ethernet_hdr *)receive_buffer[rx_packet_idx]; protlen = ntohs(eth_hdr->et_protlen); if (protlen == 0x8100) { hdr_size += 4; - protlen = ntohs(*(u16 *)&net_rx_packet[hdr_size - 2]); + protlen = ntohs(*(u16 *)&receive_buffer[rx_packet_idx][hdr_size - 2]); } if (header_size) *header_size = hdr_size; @@ -621,17 +628,22 @@ static efi_status_t EFIAPI efi_net_receive memcpy(src_addr, eth_hdr->et_src, ARP_HLEN); if (protocol) *protocol = protlen; - if (*buffer_size < net_rx_packet_len) { + if (*buffer_size < receive_lengths[rx_packet_idx]) { /* Packet doesn't fit, try again with bigger buffer */ - *buffer_size = net_rx_packet_len; + *buffer_size = receive_lengths[rx_packet_idx]; ret = EFI_BUFFER_TOO_SMALL; goto out; } /* Copy packet */ - memcpy(buffer, net_rx_packet, net_rx_packet_len); - *buffer_size = net_rx_packet_len; - new_rx_packet = 0; - this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + memcpy(buffer, receive_buffer[rx_packet_idx], + receive_lengths[rx_packet_idx]); + *buffer_size = receive_lengths[rx_packet_idx]; + rx_packet_idx = (rx_packet_idx + 1) % ETH_PACKETS_BATCH_RECV; + rx_packet_num--; + if (rx_packet_num) + wait_for_packet->is_signaled = true; + else + this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; out: return EFI_EXIT(ret); } @@ -664,7 +676,26 @@ void efi_net_set_dhcp_ack(void *pkt, int len) */ static void efi_net_push(void *pkt, int len) { - new_rx_packet = true; + int rx_packet_next; + + /* Check that we at least received an Ethernet header */ + if (len < sizeof(struct ethernet_hdr)) + return; + + /* Check that the buffer won't overflow */ + if (len > PKTSIZE_ALIGN) + return; + + /* Can't store more than pre-alloced buffer */ + if (rx_packet_num >= ETH_PACKETS_BATCH_RECV) + return; + + rx_packet_next = (rx_packet_idx + rx_packet_num) % + ETH_PACKETS_BATCH_RECV; + memcpy(receive_buffer[rx_packet_next], pkt, len); + receive_lengths[rx_packet_next] = len; + + rx_packet_num++; } /** @@ -689,20 +720,14 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event, if (!this || this->mode->state != EFI_NETWORK_INITIALIZED) goto out; - if (!new_rx_packet) { + if (!rx_packet_num) { push_packet = efi_net_push; eth_rx(); push_packet = NULL; - if (new_rx_packet) { - /* Check that we at least received an Ethernet header */ - if (net_rx_packet_len >= - sizeof(struct ethernet_hdr)) { - this->int_status |= - EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; - wait_for_packet->is_signaled = true; - } else { - new_rx_packet = 0; - } + if (rx_packet_num) { + this->int_status |= + EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + wait_for_packet->is_signaled = true; } } out: @@ -830,6 +855,7 @@ efi_status_t efi_net_register(void) { struct efi_net_obj *netobj = NULL; efi_status_t r; + int i; if (!eth_get_dev()) { /* No network device active, don't expose any */ @@ -847,6 +873,21 @@ efi_status_t efi_net_register(void) goto out_of_resources; transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN); + /* Allocate a number of receive buffers */ + receive_buffer = calloc(ETH_PACKETS_BATCH_RECV, + sizeof(*receive_buffer)); + if (!receive_buffer) + goto out_of_resources; + for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) { + receive_buffer[i] = malloc(PKTSIZE_ALIGN); + if (!receive_buffer[i]) + goto out_of_resources; + } + receive_lengths = calloc(ETH_PACKETS_BATCH_RECV, + sizeof(*receive_lengths)); + if (!receive_lengths) + goto out_of_resources; + /* Hook net up to the device list */ efi_add_handle(&netobj->header); @@ -941,7 +982,12 @@ failure_to_add_protocol: return r; out_of_resources: free(netobj); - /* free(transmit_buffer) not needed yet */ + free(transmit_buffer); + if (receive_buffer) + for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) + free(receive_buffer[i]); + free(receive_buffer); + free(receive_lengths); printf("ERROR: Out of memory\n"); return EFI_OUT_OF_RESOURCES; } diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index dea2b4e5ee..1fa1595e40 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -266,9 +266,13 @@ static efi_status_t EFIAPI efi_get_time_boottime( time->hour = tm.tm_hour; time->minute = tm.tm_min; time->second = tm.tm_sec; - if (tm.tm_isdst) + if (tm.tm_isdst > 0) time->daylight = EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT; + else if (!tm.tm_isdst) + time->daylight = EFI_TIME_ADJUST_DAYLIGHT; + else + time->daylight = 0; time->timezone = EFI_UNSPECIFIED_TIMEZONE; if (capabilities) { @@ -347,8 +351,17 @@ static efi_status_t EFIAPI efi_set_time_boottime(struct efi_time *time) tm.tm_hour = time->hour; tm.tm_min = time->minute; tm.tm_sec = time->second; - tm.tm_isdst = time->daylight == - (EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT); + switch (time->daylight) { + case EFI_TIME_ADJUST_DAYLIGHT: + tm.tm_isdst = 0; + break; + case EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT: + tm.tm_isdst = 1; + break; + default: + tm.tm_isdst = -1; + break; + } /* Calculate day of week */ rtc_calc_weekday(&tm); |