Skip to content

Instantly share code, notes, and snippets.

@heiher
Created June 20, 2022 07:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heiher/4310e216e40c59edd85f4a74cbfede1f to your computer and use it in GitHub Desktop.
Save heiher/4310e216e40c59edd85f4a74cbfede1f to your computer and use it in GitHub Desktop.
GRUB EFI Serial Read workaround for 3A5000
diff --git a/grub-core/term/efi/serial.c b/grub-core/term/efi/serial.c
index 4c94723..0caa724 100644
--- a/grub-core/term/efi/serial.c
+++ b/grub-core/term/efi/serial.c
@@ -65,20 +65,52 @@ do_real_config (struct grub_serial_port *port)
port->configured = 1;
}
+#define SERIAL_BASE 0x800000001fe001e0ul
+
+#define SERIAL_DAT 0
+#define SERIAL_DLL 0
+#define SERIAL_DLM 1
+#define SERIAL_IER 1
+#define SERIAL_IIR 2
+#define SERIAL_FCR 2
+#define SERIAL_LCR 3
+#define SERIAL_MCR 4
+#define SERIAL_LSR 5
+
+#define SERIAL_LCR_DLAB 0x80
+#define SERIAL_LSR_TE 0x20
+
+#define PORT(base, offset) (volatile unsigned char *)(base + offset)
+
+static inline unsigned int
+serial_in (int offset)
+{
+ return *(PORT(SERIAL_BASE, offset));
+}
+
+static int
+serial_read (void *buf, int len)
+{
+ unsigned char *data = buf;
+ int i;
+
+ for (i=0; i<len; i++) {
+ while ((serial_in (SERIAL_LSR) & 1) == 0) {
+ grub_efi_stall(10);
+ }
+ data[i] = serial_in (SERIAL_DAT);
+ }
+
+ return len;
+}
+
/* Fetch a key. */
static int
serial_hw_fetch (struct grub_serial_port *port)
{
- grub_efi_uintn_t bufsize = 1;
char c;
- grub_efi_status_t status = GRUB_EFI_SUCCESS;
- do_real_config (port);
- if (port->broken)
- return -1;
- status = efi_call_3 (port->interface->read, port->interface, &bufsize, &c);
- if (status != GRUB_EFI_SUCCESS || bufsize == 0)
- return -1;
+ serial_read (&c, sizeof (c));
return c;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment