grub2/0024-arm_coreboot-Support-keyboard-for-vexpress.patch
Javier Martinez Canillas afb0baacd6
Use BLS fragment filename as menu entry id and for sort criterion
The BLS config filenames are guaranteed to be unique, so they can be
used as GRUB2 entry id and can also be used to sort the menu entries.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2018-07-02 17:33:09 +02:00

249 lines
6.5 KiB
Diff

From 848bed9d92cf20e9f25db4c69a20efad23996ca0 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Mon, 8 May 2017 21:42:37 +0200
Subject: [PATCH 024/250] arm_coreboot: Support keyboard for vexpress.
---
grub-core/Makefile.core.def | 3 +
grub-core/kern/arm/coreboot/init.c | 1 +
grub-core/term/arm/pl050.c | 189 +++++++++++++++++++++++++++++++++++++
grub-core/Makefile.am | 1 +
4 files changed, 194 insertions(+)
create mode 100644 grub-core/term/arm/pl050.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 6ade6e95057..6be6e7f61ee 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -160,6 +160,9 @@ kernel = {
arm_coreboot = kern/arm/coreboot/coreboot.S;
arm_coreboot = lib/fdt.c;
arm_coreboot = bus/fdt.c;
+ arm_coreboot = term/ps2.c;
+ arm_coreboot = term/arm/pl050.c;
+ arm_coreboot = commands/keylayouts.c;
terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c;
diff --git a/grub-core/kern/arm/coreboot/init.c b/grub-core/kern/arm/coreboot/init.c
index aec75c672a2..a06ccb72f42 100644
--- a/grub-core/kern/arm/coreboot/init.c
+++ b/grub-core/kern/arm/coreboot/init.c
@@ -133,6 +133,7 @@ grub_machine_init (void)
grub_fdtbus_init (dtb, dtb_size);
grub_machine_timer_init ();
+ grub_pl050_init ();
}
void
diff --git a/grub-core/term/arm/pl050.c b/grub-core/term/arm/pl050.c
new file mode 100644
index 00000000000..e4cda305666
--- /dev/null
+++ b/grub-core/term/arm/pl050.c
@@ -0,0 +1,189 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/ps2.h>
+#include <grub/fdtbus.h>
+#include <grub/err.h>
+#include <grub/machine/kernel.h>
+#include <grub/at_keyboard.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/time.h>
+#include <grub/ps2.h>
+#include <grub/fdtbus.h>
+
+static volatile grub_uint32_t *pl050_regs;
+
+struct grub_ps2_state ps2_state;
+
+static void
+keyboard_controller_wait_until_ready (void)
+{
+ while (! (pl050_regs[1] & 0x40));
+}
+
+static grub_uint8_t
+wait_ack (void)
+{
+ grub_uint64_t endtime;
+ grub_uint8_t ack;
+
+ endtime = grub_get_time_ms () + 20;
+ do
+ ack = pl050_regs[2];
+ while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
+ && grub_get_time_ms () < endtime);
+ return ack;
+}
+
+
+static int
+write_mode (int mode)
+{
+ unsigned i;
+ for (i = 0; i < GRUB_AT_TRIES; i++)
+ {
+ grub_uint8_t ack;
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = 0xf0;
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = mode;
+ keyboard_controller_wait_until_ready ();
+ ack = wait_ack ();
+ if (ack == GRUB_AT_NACK)
+ continue;
+ if (ack == GRUB_AT_ACK)
+ break;
+ return 0;
+ }
+
+ return (i != GRUB_AT_TRIES);
+}
+
+static int
+query_mode (void)
+{
+ grub_uint8_t ret;
+ int e;
+
+ e = write_mode (0);
+ if (!e)
+ return 0;
+
+ keyboard_controller_wait_until_ready ();
+
+ do
+ ret = pl050_regs[2];
+ while (ret == GRUB_AT_ACK);
+
+ /* QEMU translates the set even in no-translate mode. */
+ if (ret == 0x43 || ret == 1)
+ return 1;
+ if (ret == 0x41 || ret == 2)
+ return 2;
+ if (ret == 0x3f || ret == 3)
+ return 3;
+ return 0;
+}
+
+static void
+set_scancodes (void)
+{
+ write_mode (2);
+ ps2_state.current_set = query_mode ();
+ grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+ if (ps2_state.current_set == 2)
+ return;
+
+ write_mode (1);
+ ps2_state.current_set = query_mode ();
+ grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+ if (ps2_state.current_set == 1)
+ return;
+ grub_dprintf ("atkeyb", "no supported scancode set found\n");
+}
+
+static void
+keyboard_controller_led (grub_uint8_t leds)
+{
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = 0xed;
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = leds & 0x7;
+}
+
+/* If there is a character pending, return it;
+ otherwise return GRUB_TERM_NO_KEY. */
+static int
+grub_pl050_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+ grub_uint8_t at_key;
+ int ret;
+ grub_uint8_t old_led;
+
+ if (!(pl050_regs[1] & 0x10))
+ return -1;
+ at_key = pl050_regs[2];
+ old_led = ps2_state.led_status;
+
+ ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
+ if (old_led != ps2_state.led_status)
+ keyboard_controller_led (ps2_state.led_status);
+ return ret;
+}
+
+static struct grub_term_input grub_pl050_keyboard_term =
+ {
+ .name = "pl050_keyboard",
+ .getkey = grub_pl050_keyboard_getkey
+ };
+
+static grub_err_t
+pl050_attach(const struct grub_fdtbus_dev *dev)
+{
+ const grub_uint32_t *reg;
+ reg = grub_fdtbus_get_prop (dev, "reg", 0);
+
+ /* Mouse. Nothing to do. */
+ if (grub_be_to_cpu32 (*reg) == 0x7000)
+ return 0;
+
+ pl050_regs = grub_fdtbus_map_reg (dev, 0, 0);
+
+ if (!grub_fdtbus_is_mapping_valid (pl050_regs))
+ return grub_error (GRUB_ERR_IO, "could not map pl050");
+
+ ps2_state.at_keyboard_status = 0;
+ set_scancodes ();
+ keyboard_controller_led (ps2_state.led_status);
+
+ grub_term_register_input ("pl050_keyboard", &grub_pl050_keyboard_term);
+ return GRUB_ERR_NONE;
+}
+
+struct grub_fdtbus_driver pl050 =
+{
+ .compatible = "arm,pl050",
+ .attach = pl050_attach
+};
+
+void
+grub_pl050_init (void)
+{
+ grub_fdtbus_register (&pl050);
+}
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 147e6959c97..a2aaf9f54b0 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -240,6 +240,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
endif
if COND_arm_coreboot
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
--
2.17.1