aboutsummaryrefslogtreecommitdiff
path: root/lib/efi_loader
diff options
context:
space:
mode:
Diffstat (limited to 'lib/efi_loader')
-rw-r--r--lib/efi_loader/efi_boottime.c13
-rw-r--r--lib/efi_loader/efi_console.c20
-rw-r--r--lib/efi_loader/efi_net.c92
-rw-r--r--lib/efi_loader/efi_runtime.c19
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);