diff options
author | Leah Rowe <leah@libreboot.org> | 2025-10-02 23:47:31 +0100 |
---|---|---|
committer | Leah Rowe <leah@libreboot.org> | 2025-10-02 23:48:48 +0100 |
commit | af88a066d0e4fc5aaa63b2e7a4989d1f64b3f7b2 (patch) | |
tree | 070807dcf18f99f9bc3a070bbb55dddd23af199b /config/grub/xhci | |
parent | d90defeae3e4e7c91ba521e44071d962abb33d3f (diff) |
grub/xhci: rename to grub/xhci_nvme
we have the "default" tree, then the "nvme" tree which adds
nvme support.
the "xhci" tree adds xhci patches, *and* nvme patches.
riku suggested that i rename it accordingly, and his advice
was quite correct, indeed wise.
this will reduce confusion for contributors, including *myself*.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'config/grub/xhci')
28 files changed, 0 insertions, 8420 deletions
diff --git a/config/grub/xhci/config/payload b/config/grub/xhci/config/payload deleted file mode 100644 index 9db22fe2..00000000 --- a/config/grub/xhci/config/payload +++ /dev/null @@ -1,321 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# Copyright (C) 2014-2016,2020-2021,2023-2025 Leah Rowe <leah@libreboot.org> -# Copyright (C) 2015 Klemens Nanni <contact@autoboot.org> - -set prefix=(memdisk)/boot/grub - -insmod at_keyboard -insmod usb_keyboard -insmod nativedisk -insmod xhci -insmod ehci -insmod ohci -insmod uhci -insmod usb -insmod usbms -insmod regexp - -terminal_input --append at_keyboard -terminal_input --append usb_keyboard -terminal_output --append cbmemc - -# User interface overrides wherever "keystatus" is supported -# Keep SHIFT key pressed before powering on to disable graphics -if keystatus --shift; then - terminal_output --append vga_text -else - gfxpayload=keep - terminal_output --append gfxterm - - for dt in cbfsdisk memdisk; do - for it in png jpg; do - if [ -f (${dt})/background.${it} ]; then - insmod ${it} - background_image (${dt})/background.${it} - fi - done - done -fi - -# Keep CTRL pressed to enable default serial terminal (COM1 or the like) -if keystatus --ctrl; then - serial - terminal_input --append serial - terminal_output --append serial -fi - -# Keep ALT pressed to enable spkmodem -if keystatus --alt; then - terminal_output --append spkmodem -fi - - -set default="0" -if [ -f (cbfsdisk)/timeout.cfg ]; then - source (cbfsdisk)/timeout.cfg -else - set timeout=8 -fi -set grub_scan_disk="nvme ahci ata" -if [ -f (cbfsdisk)/scan.cfg ]; then - source (cbfsdisk)/scan.cfg -fi - -if [ -f (cbfsdisk)/keymap.gkb ]; then - keymap (cbfsdisk)/keymap.gkb -fi - -function really_try_user_config { - set root="${1}" - - if [ -f /"${2}"/grub.cfg ]; then - unset superusers - configfile /"${2}"/grub.cfg - fi -} - -function try_user_config { - # The @/... entries are for cases where the BTRFS filesystem is being used - for dir in grub boot/grub @/grub @/boot/grub grub2 boot/grub2 @/grub2 @/boot/grub2 boot @/boot; do - really_try_user_config "${1}" "${dir}" - done - for dir in ubuntu debian redhat; do - really_try_user_config "${1}" "EFI/${dir}" - done -} -function search_grub { - echo -n "Attempting to load grub.cfg from '${1}' devices" - for i in 0 1 2 3 4 5 6 7 8; do - for part in 1 2 3 4 5 6 7 8 9 10 11 12; do - if [ "${1}" != "nvme" ]; then - try_user_config "(${1}${i},${part})" - else - # TODO: do we care about other namesapces - try_user_config "(nvme${i}n1,${part})" - fi - done - if [ "${1}" != "nvme" ]; then - # raw devices e.g. (ahci0) instead of (ahci0,1) - try_user_config "(${1}${i})" - else - # TODO: do we care about other namesapces - try_user_config "(nvme${i}n1)" - fi - done - echo # Insert newline -} - -function try_isolinux_config { - set root="${1}" - for dir in '' /boot /EFI /@ /@/boot; do - if [ -f "${dir}"/isolinux/isolinux.cfg ]; then - syslinux_configfile -i "${dir}"/isolinux/isolinux.cfg - elif [ -f "${dir}"/syslinux/syslinux.cfg ]; then - syslinux_configfile -s "${dir}"/syslinux/syslinux.cfg - elif [ -f "${dir}"/syslinux/extlinux.conf ]; then - syslinux_configfile -s "${dir}"/syslinux/extlinux.conf - elif [ -f "${dir}"/extlinux/extlinux.conf ]; then - syslinux_configfile -s "${dir}"/extlinux/extlinux.conf - fi - done -} -function search_isolinux { - echo "\nAttempting to parse iso/sys/extlinux config from '${1}' devices" - for i in 0 1 2 3 4 5 6 7 8; do - for part in 1 2 3 4 5 6 7 8 9 10 11 12; do - if [ "${1}" != "nvme" ]; then - try_isolinux_config "(${1}${i},${part})" - else - # TODO: see above - try_isolinux_config "(nvme${i}n1,${part})" - fi - done - if [ "${1}" != "nvme" ]; then - # raw devices e.g. (usb0) instead of (usb0,1) - try_isolinux_config "(${1}${i})" - else - # TODO: do we care about other namesapces - try_isolinux_config "(nvme${i}n1)" - fi - done - echo # Insert newline -} -function try_bootcfg { - try_user_config "${1}" - try_isolinux_config "${1}" -} -function search_bootcfg { - search_grub "${1}" - search_isolinux "${1}" -} -menuentry 'Load Operating System (incl. fully encrypted disks) [o]' --hotkey='o' { - - for grub_disk in ${grub_scan_disk}; do - search_bootcfg ${grub_disk} - done - - # grub device enumeration is very slow, so checks are hardcoded - - raidvol="md/0 md/1 md/2 md/3 md/4 md/5 md/6 md/7 md/8 md/9" - - # in practise, doing multiple redundant checks is perfectly fast - # TODO: optimize grub itself, and use */? here for everything - - for vol in ${raidvol} ; do - try_bootcfg "${vol}" - done - - unset bootdev - for grub_disk in ${grub_scan_disk}; do - for i in 0 1 2 3 4 5 6 7 8; do - for part in 1 2 3 4 5 6 7 8 9 10 11 12; do - if [ "${grub_disk}" = "ahci" ]; then - bootdev="${bootdev} (ahci${i},${part})" - elif [ "${grub_disk}" = "ata" ]; then - bootdev="${bootdev} (ata${i},${part})" - elif [ "${grub_disk}" = "nvme" ]; then - # TODO: do we care about other namesapces - bootdev="${bootdev} (nvme${i}n1,${part})" - fi - done - done - done - - set pager=0 - echo -n "Attempting to unlock encrypted volumes" - for dev in ${bootdev} ${raidvol}; do - if cryptomount "${dev}" ; then break ; fi - done - set pager=1 - echo - - search_bootcfg crypto - - lvmvol="" - - # after cryptomount, lvm volumes might be available - # using * is slow on some machines, but we use it here, - # just once. in so doing, we find every lvm volume - for vol in (*); do - if regexp ^\\(lvm/ $vol; then - lvmvol="${lvmvol} ${vol}" - try_bootcfg "${vol}" - fi - done - - # user might have put luks inside lvm - set pager=0 - echo "Attempting to unlock encrypted LVMs" - for vol in ${lvmvol}; do - cryptomount "$vol" - done - set pager=1 - echo - - search_bootcfg crypto - - true # Prevent pager requiring to accept each line instead of whole screen -} - -menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on USB [s]' --hotkey='s' { - search_bootcfg usb -} -menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on AHCI [a]' --hotkey='a' { - search_bootcfg ahci -} -menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on ATA/IDE [d]' --hotkey='d' { - search_bootcfg ata -} -menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on NVMe [e]' --hotkey='e' { - search_bootcfg nvme -} -if [ -f (cbfsdisk)/grub.cfg ]; then -menuentry 'Load configuration (grub.cfg) in CBFS [t]' --hotkey='t' { - set root='(cbfsdisk)' - if [ -f /grub.cfg ]; then - configfile /grub.cfg - fi -} -fi -if [ -f (cbfsdisk)/grubtest.cfg ]; then -menuentry 'Load test configuration (grubtest.cfg) in CBFS [t]' --hotkey='t' { - set root='(cbfsdisk)' - if [ -f /grubtest.cfg ]; then - configfile /grubtest.cfg - fi -} -fi -if [ -f (cbfsdisk)/u-boot ]; then -menuentry 'U-Boot i386 payload (experimental) [u]' --hotkey='u' { - set root='cbfsdisk' - chainloader /u-boot -} -fi -if [ -f (cbfsdisk)/seabios.elf ]; then -if [ -f (cbfsdisk)/img/u-boot ]; then -menuentry 'Load SeaBIOS (U-Boot UEFI available in the ESC menu) [b]' --hotkey='b' { - set root='cbfsdisk' - chainloader /seabios.elf -} -else -menuentry 'Load SeaBIOS [b]' --hotkey='b' { - set root='cbfsdisk' - chainloader /seabios.elf -} -fi -fi -if [ -f (cbfsdisk)/img/grub2 ]; then -if [ -f (cbfsdisk)/img/u-boot ]; then -menuentry 'Return to SeaBIOS (U-Boot UEFI available in the ESC menu) [b]' --hotkey='b' { - set root='cbfsdisk' - chainloader /fallback/payload -} -else -menuentry 'Return to SeaBIOS [b]' --hotkey='b' { - set root='cbfsdisk' - chainloader /fallback/payload -} -fi -fi -menuentry 'Poweroff [p]' --hotkey='p' { - halt -} -menuentry 'Reboot [r]' --hotkey='r' { - reboot -} -if [ -f (cbfsdisk)/img/memtest ]; then -menuentry 'Load MemTest86+ [m]' --hotkey='m' { - set root='cbfsdisk' - chainloader /img/memtest -} -fi - -submenu 'Other [z]' --hotkey='z' { - menuentry 'Enable default serial terminal [s]' --hotkey='s' { - serial - terminal_input --append serial - terminal_output --append serial - } - - menuentry 'Disable default serial terminal' { - terminal_input --remove serial - terminal_output --remove serial - } - - menuentry 'Enable gfxterm' { - terminal_output --append gfxterm - terminal_output --remove vga_text - } - menuentry 'Disable gfxterm [g]' --hotkey='g' { - terminal_output --remove gfxterm - terminal_output --append vga_text - } - - menuentry 'Enable spkmodem [a]' --hotkey='a' { - terminal_output --append spkmodem - } - - menuentry 'Disable spkmodem [z]' --hotkey='z' { - terminal_output --remove spkmodem - } -} diff --git a/config/grub/xhci/patches/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch b/config/grub/xhci/patches/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch deleted file mode 100644 index d480d60a..00000000 --- a/config/grub/xhci/patches/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 6a04ceb244366ddab75ce229afd19687ce35d15a Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 31 Oct 2021 03:47:05 +0000 -Subject: [PATCH 01/26] mitigate grub's missing characters for borders/arrow - characters - -This cleans up the display on the main screen in GRUB. - -Just don't draw a border, at all. ---- - grub-core/normal/menu_text.c | 49 ++---------------------------------- - 1 file changed, 2 insertions(+), 47 deletions(-) - -diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c -index 9c383e64a..8ec1dd1e8 100644 ---- a/grub-core/normal/menu_text.c -+++ b/grub-core/normal/menu_text.c -@@ -108,47 +108,6 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right, - grub_print_message_indented_real (msg, margin_left, margin_right, term, 0); - } - --static void --draw_border (struct grub_term_output *term, const struct grub_term_screen_geometry *geo) --{ -- int i; -- -- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); -- -- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1, -- geo->first_entry_y - 1 }); -- grub_putcode (GRUB_UNICODE_CORNER_UL, term); -- for (i = 0; i < geo->entry_width + 1; i++) -- grub_putcode (GRUB_UNICODE_HLINE, term); -- grub_putcode (GRUB_UNICODE_CORNER_UR, term); -- -- for (i = 0; i < geo->num_entries; i++) -- { -- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1, -- geo->first_entry_y + i }); -- grub_putcode (GRUB_UNICODE_VLINE, term); -- grub_term_gotoxy (term, -- (struct grub_term_coordinate) { geo->first_entry_x + geo->entry_width + 1, -- geo->first_entry_y + i }); -- grub_putcode (GRUB_UNICODE_VLINE, term); -- } -- -- grub_term_gotoxy (term, -- (struct grub_term_coordinate) { geo->first_entry_x - 1, -- geo->first_entry_y - 1 + geo->num_entries + 1 }); -- grub_putcode (GRUB_UNICODE_CORNER_LL, term); -- for (i = 0; i < geo->entry_width + 1; i++) -- grub_putcode (GRUB_UNICODE_HLINE, term); -- grub_putcode (GRUB_UNICODE_CORNER_LR, term); -- -- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); -- -- grub_term_gotoxy (term, -- (struct grub_term_coordinate) { geo->first_entry_x - 1, -- (geo->first_entry_y - 1 + geo->num_entries -- + GRUB_TERM_MARGIN + 1) }); --} -- - static int - print_message (int nested, int edit, struct grub_term_output *term, int dry_run) - { -@@ -167,10 +126,8 @@ command-line or ESC to discard edits and return to the GRUB menu."), - { - char *msg_translated; - -- msg_translated = grub_xasprintf (_("Use the %C and %C keys to select which " -- "entry is highlighted."), -- GRUB_UNICODE_UPARROW, -- GRUB_UNICODE_DOWNARROW); -+ msg_translated = grub_xasprintf (_("Use the arrow keys to select which " -+ "entry is highlighted.")); - if (!msg_translated) - return 0; - ret += grub_print_message_indented_real (msg_translated, STANDARD_MARGIN, -@@ -413,8 +370,6 @@ grub_menu_init_page (int nested, int edit, - - grub_term_normal_color = grub_color_menu_normal; - grub_term_highlight_color = grub_color_menu_highlight; -- if (geo->border) -- draw_border (term, geo); - grub_term_normal_color = old_color_normal; - grub_term_highlight_color = old_color_highlight; - geo->timeout_y = geo->first_entry_y + geo->num_entries --- -2.39.5 - diff --git a/config/grub/xhci/patches/0002-say-the-name-libreboot-in-the-grub-menu.patch b/config/grub/xhci/patches/0002-say-the-name-libreboot-in-the-grub-menu.patch deleted file mode 100644 index e50e6c6a..00000000 --- a/config/grub/xhci/patches/0002-say-the-name-libreboot-in-the-grub-menu.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c18175417d4fa4501dac21ef26b9c30f67ece0fd Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sat, 19 Nov 2022 16:30:24 +0000 -Subject: [PATCH 02/26] say the name libreboot, in the grub menu - ---- - grub-core/normal/main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c -index 96abfda2f..d806db9c4 100644 ---- a/grub-core/normal/main.c -+++ b/grub-core/normal/main.c -@@ -209,7 +209,7 @@ grub_normal_init_page (struct grub_term_output *term, - - grub_term_cls (term); - -- msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION); -+ msg_formatted = grub_xasprintf (_("Libreboot 25.06 Luminous Lemon (GRUB menu): https://libreboot.org/")); - if (!msg_formatted) - return; - --- -2.39.5 - diff --git a/config/grub/xhci/patches/0003-Add-CC0-license.patch b/config/grub/xhci/patches/0003-Add-CC0-license.patch deleted file mode 100644 index c2fd1c01..00000000 --- a/config/grub/xhci/patches/0003-Add-CC0-license.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 72b0b0f76b3cc7f03e42322b77400b89c3ccf766 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 03/26] Add CC0 license - -Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> ---- - grub-core/kern/dl.c | 3 ++- - util/grub-module-verifierXX.c | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index de8c3aa8d..4a3be8568 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -495,7 +495,8 @@ grub_dl_check_license (grub_dl_t mod, Elf_Ehdr *e) - - if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 -- || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0) -+ || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0 -+ || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=CC0") == 0) - return GRUB_ERR_NONE; - - return grub_error (GRUB_ERR_BAD_MODULE, -diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c -index a42c20bd1..7157a30aa 100644 ---- a/util/grub-module-verifierXX.c -+++ b/util/grub-module-verifierXX.c -@@ -236,7 +236,8 @@ check_license (const char * const filename, - Elf_Shdr *s = find_section (arch, e, ".module_license", module_size); - if (s && (strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3") == 0 - || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3+") == 0 -- || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0)) -+ || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0 -+ || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=CC0") == 0)) - return; - grub_util_error ("%s: incompatible license", filename); - } --- -2.39.5 - diff --git a/config/grub/xhci/patches/0004-Define-GRUB_UINT32_MAX.patch b/config/grub/xhci/patches/0004-Define-GRUB_UINT32_MAX.patch deleted file mode 100644 index d41c802e..00000000 --- a/config/grub/xhci/patches/0004-Define-GRUB_UINT32_MAX.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 451ca97719aa9178f3202554c74ab636baece616 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 04/26] Define GRUB_UINT32_MAX - -Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> ---- - include/grub/types.h | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/include/grub/types.h b/include/grub/types.h -index 45079bf65..8c0b30395 100644 ---- a/include/grub/types.h -+++ b/include/grub/types.h -@@ -156,6 +156,7 @@ typedef grub_int32_t grub_ssize_t; - #define GRUB_SHRT_MAX 0x7fff - #define GRUB_SHRT_MIN (-GRUB_SHRT_MAX - 1) - #define GRUB_UINT_MAX 4294967295U -+#define GRUB_UINT32_MAX 4294967295U - #define GRUB_INT_MAX 0x7fffffff - #define GRUB_INT_MIN (-GRUB_INT_MAX - 1) - #define GRUB_INT32_MAX 2147483647 -@@ -177,6 +178,13 @@ typedef grub_int32_t grub_ssize_t; - #define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0))) - #define GRUB_TYPE_U_MIN(type) 0ULL - -+# define GRUB_UINT32_C(x) x ## U -+# if GRUB_ULONG_MAX >> 31 >> 31 >> 1 == 1 -+# define GRUB_UINT64_C(x) x##UL -+# elif 1 -+# define GRUB_UINT64_C(x) x##ULL -+# endif -+ - typedef grub_uint64_t grub_properly_aligned_t; - - #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] --- -2.39.5 - diff --git a/config/grub/xhci/patches/0005-Add-Argon2-algorithm.patch b/config/grub/xhci/patches/0005-Add-Argon2-algorithm.patch deleted file mode 100644 index d2d202db..00000000 --- a/config/grub/xhci/patches/0005-Add-Argon2-algorithm.patch +++ /dev/null @@ -1,2612 +0,0 @@ -From 93404ba667dae9a5da9953f7a17245adfe529c78 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 05/26] Add Argon2 algorithm - -Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> ---- - docs/grub-dev.texi | 64 +++ - grub-core/Makefile.core.def | 8 + - grub-core/lib/argon2/LICENSE | 314 +++++++++++ - grub-core/lib/argon2/argon2.c | 232 ++++++++ - grub-core/lib/argon2/argon2.h | 264 +++++++++ - grub-core/lib/argon2/blake2/blake2-impl.h | 151 ++++++ - grub-core/lib/argon2/blake2/blake2.h | 89 +++ - grub-core/lib/argon2/blake2/blake2b.c | 388 ++++++++++++++ - .../lib/argon2/blake2/blamka-round-ref.h | 56 ++ - grub-core/lib/argon2/core.c | 506 ++++++++++++++++++ - grub-core/lib/argon2/core.h | 228 ++++++++ - grub-core/lib/argon2/ref.c | 190 +++++++ - 12 files changed, 2490 insertions(+) - create mode 100644 grub-core/lib/argon2/LICENSE - create mode 100644 grub-core/lib/argon2/argon2.c - create mode 100644 grub-core/lib/argon2/argon2.h - create mode 100644 grub-core/lib/argon2/blake2/blake2-impl.h - create mode 100644 grub-core/lib/argon2/blake2/blake2.h - create mode 100644 grub-core/lib/argon2/blake2/blake2b.c - create mode 100644 grub-core/lib/argon2/blake2/blamka-round-ref.h - create mode 100644 grub-core/lib/argon2/core.c - create mode 100644 grub-core/lib/argon2/core.h - create mode 100644 grub-core/lib/argon2/ref.c - -diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi -index f4367f895..9d96cedf9 100644 ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -503,12 +503,76 @@ GRUB includes some code from other projects, and it is sometimes necessary - to update it. - - @menu -+* Argon2:: - * Gnulib:: - * jsmn:: - * minilzo:: - * libtasn1:: - @end menu - -+@node Argon2 -+@section Argon2 -+ -+Argon2 is a key derivation function used by LUKS2 in order to derive encryption -+keys from a user-provided password. GRUB imports the official reference -+implementation of Argon2 from @url{https://github.com/P-H-C/phc-winner-argon2}. -+In order to make the library usable for GRUB, we need to perform various -+conversions. This is mainly due to the fact that the imported code makes use of -+types and functions defined in the C standard library, which isn't available. -+Furthermore, using the POSIX wrapper library is not possible as the code needs -+to be part of the kernel. -+ -+Updating the code can thus be performed like following: -+ -+@example -+$ git clone https://github.com/P-H-C/phc-winner-argon2 argon2 -+$ cp argon2/include/argon2.h argon2/src/@{argon2.c,core.c,core.h,ref.c@} \ -+ grub-core/lib/argon2/ -+$ cp argon2/src/blake2/@{blake2-impl.h,blake2.h,blake2b.c,blamka-round-ref.h@} \ -+ grub-core/lib/argon2/blake2/ -+$ sed -e 's/UINT32_C/GRUB_UINT32_C/g' \ -+ -e 's/UINT64_C/GRUB_UINT64_C/g' \ -+ -e 's/UINT32_MAX/GRUB_UINT32_MAX/g' \ -+ -e 's/CHAR_BIT/GRUB_CHAR_BIT/g' \ -+ -e 's/UINT_MAX/GRUB_UINT_MAX/g' \ -+ -e 's/uintptr_t/grub_addr_t/g' \ -+ -e 's/size_t/grub_size_t/g' \ -+ -e 's/uint32_t/grub_uint32_t/g' \ -+ -e 's/uint64_t/grub_uint64_t/g' \ -+ -e 's/uint8_t/grub_uint8_t/g' \ -+ -e 's/memset/grub_memset/g' \ -+ -e 's/memcpy/grub_memcpy/g' \ -+ -e 's/malloc/grub_malloc/g' \ -+ -e 's/free/grub_free/g' \ -+ -e 's/#elif _MSC_VER/#elif defined(_MSC_VER)/' \ -+ grub-core/lib/argon2/@{*,blake2/*@}.@{c,h@} -i -+@end example -+ -+Afterwards, you need to perform the following manual steps: -+ -+@enumerate -+@item Remove all includes of standard library headers, "encoding.h" and -+ "thread.h". -+@item Add includes <grub/mm.h> and <grub/misc.h> to "argon2.h". -+@item Add include <grub/dl.h> and module license declaration to "argon2.c". -+@item Remove the following declarations and functions from "argon2.h" and -+ "argon2.c": argon2_type2string, argon2i_hash_encoded, argon2i_hash_raw, -+ argon2d_hash_encoded, argon2d_hash_raw, argon2id_hash_encoded, -+ argon2id_hash_raw, argon2_compare, argon2_verify, argon2i_verify, -+ argon2d_verify, argon2id_verify, argon2d_ctx, argon2i_ctx, argon2id_ctx, -+ argon2_verify_ctx, argon2d_verify_ctx, argon2i_verify_ctx, -+ argon2id_verify_ctx, argon2_encodedlen. -+@item Move the declaration of `clear_internal_memory()` in "blake2-impl.h" to -+ "blake2b.c". -+@item Remove code guarded by the ARGON2_NO_THREADS macro. -+@item Remove parameters `encoded` and `encodedlen` from `argon2_hash` and remove -+ the encoding block in that function. -+@item Remove parameter verifications in `validate_inputs()` for -+ ARGON2_MIN_PWD_LENGTH, ARGON2_MIN_SECRET, ARGON2_MIN_AD_LENGTH and -+ ARGON2_MAX_MEMORY to fix compiler warnings. -+@item Mark the function argon2_ctx as static. -+@end enumerate -+ - @node Gnulib - @section Gnulib - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 24e8c8437..0ee65d54d 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1219,6 +1219,14 @@ module = { - common = lib/json/json.c; - }; - -+module = { -+ name = argon2; -+ common = lib/argon2/argon2.c; -+ common = lib/argon2/core.c; -+ common = lib/argon2/ref.c; -+ common = lib/argon2/blake2/blake2b.c; -+}; -+ - module = { - name = afsplitter; - common = disk/AFSplitter.c; -diff --git a/grub-core/lib/argon2/LICENSE b/grub-core/lib/argon2/LICENSE -new file mode 100644 -index 000000000..97aae2925 ---- /dev/null -+++ b/grub-core/lib/argon2/LICENSE -@@ -0,0 +1,314 @@ -+Argon2 reference source code package - reference C implementations -+ -+Copyright 2015 -+Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ -+You may use this work under the terms of a Creative Commons CC0 1.0 -+License/Waiver or the Apache Public License 2.0, at your option. The terms of -+these licenses can be found at: -+ -+- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ -+The terms of the licenses are reproduced below. -+ -+-------------------------------------------------------------------------------- -+ -+Creative Commons Legal Code -+ -+CC0 1.0 Universal -+ -+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE -+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN -+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS -+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES -+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS -+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM -+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED -+ HEREUNDER. -+ -+Statement of Purpose -+ -+The laws of most jurisdictions throughout the world automatically confer -+exclusive Copyright and Related Rights (defined below) upon the creator -+and subsequent owner(s) (each and all, an "owner") of an original work of -+authorship and/or a database (each, a "Work"). -+ -+Certain owners wish to permanently relinquish those rights to a Work for -+the purpose of contributing to a commons of creative, cultural and -+scientific works ("Commons") that the public can reliably and without fear -+of later claims of infringement build upon, modify, incorporate in other -+works, reuse and redistribute as freely as possible in any form whatsoever -+and for any purposes, including without limitation commercial purposes. -+These owners may contribute to the Commons to promote the ideal of a free -+culture and the further production of creative, cultural and scientific -+works, or to gain reputation or greater distribution for their Work in -+part through the use and efforts of others. -+ -+For these and/or other purposes and motivations, and without any -+expectation of additional consideration or compensation, the person -+associating CC0 with a Work (the "Affirmer"), to the extent that he or she -+is an owner of Copyright and Related Rights in the Work, voluntarily -+elects to apply CC0 to the Work and publicly distribute the Work under its -+terms, with knowledge of his or her Copyright and Related Rights in the -+Work and the meaning and intended legal effect of CC0 on those rights. -+ -+1. Copyright and Related Rights. A Work made available under CC0 may be -+protected by copyright and related or neighboring rights ("Copyright and -+Related Rights"). Copyright and Related Rights include, but are not -+limited to, the following: -+ -+ i. the right to reproduce, adapt, distribute, perform, display, -+ communicate, and translate a Work; -+ ii. moral rights retained by the original author(s) and/or performer(s); -+iii. publicity and privacy rights pertaining to a person's image or -+ likeness depicted in a Work; -+ iv. rights protecting against unfair competition in regards to a Work, -+ subject to the limitations in paragraph 4(a), below; -+ v. rights protecting the extraction, dissemination, use and reuse of data -+ in a Work; -+ vi. database rights (such as those arising under Directive 96/9/EC of the -+ European Parliament and of the Council of 11 March 1996 on the legal -+ protection of databases, and under any national implementation -+ thereof, including any amended or successor version of such -+ directive); and -+vii. other similar, equivalent or corresponding rights throughout the -+ world based on applicable law or treaty, and any national -+ implementations thereof. -+ -+2. Waiver. To the greatest extent permitted by, but not in contravention -+of, applicable law, Affirmer hereby overtly, fully, permanently, -+irrevocably and unconditionally waives, abandons, and surrenders all of -+Affirmer's Copyright and Related Rights and associated claims and causes -+of action, whether now known or unknown (including existing as well as -+future claims and causes of action), in the Work (i) in all territories -+worldwide, (ii) for the maximum duration provided by applicable law or -+treaty (including future time extensions), (iii) in any current or future -+medium and for any number of copies, and (iv) for any purpose whatsoever, -+including without limitation commercial, advertising or promotional -+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -+member of the public at large and to the detriment of Affirmer's heirs and -+successors, fully intending that such Waiver shall not be subject to -+revocation, rescission, cancellation, termination, or any other legal or -+equitable action to disrupt the quiet enjoyment of the Work by the public -+as contemplated by Affirmer's express Statement of Purpose. -+ -+3. Public License Fallback. Should any part of the Waiver for any reason -+be judged legally invalid or ineffective under applicable law, then the -+Waiver shall be preserved to the maximum extent permitted taking into -+account Affirmer's express Statement of Purpose. In addition, to the -+extent the Waiver is so judged Affirmer hereby grants to each affected -+person a royalty-free, non transferable, non sublicensable, non exclusive, -+irrevocable and unconditional license to exercise Affirmer's Copyright and -+Related Rights in the Work (i) in all territories worldwide, (ii) for the -+maximum duration provided by applicable law or treaty (including future -+time extensions), (iii) in any current or future medium and for any number -+of copies, and (iv) for any purpose whatsoever, including without -+limitation commercial, advertising or promotional purposes (the -+"License"). The License shall be deemed effective as of the date CC0 was -+applied by Affirmer to the Work. Should any part of the License for any -+reason be judged legally invalid or ineffective under applicable law, such -+partial invalidity or ineffectiveness shall not invalidate the remainder -+of the License, and in such case Affirmer hereby affirms that he or she -+will not (i) exercise any of his or her remaining Copyright and Related -+Rights in the Work or (ii) assert any associated claims and causes of -+action with respect to the Work, in either case contrary to Affirmer's -+express Statement of Purpose. -+ -+4. Limitations and Disclaimers. -+ -+ a. No trademark or patent rights held by Affirmer are waived, abandoned, -+ surrendered, licensed or otherwise affected by this document. -+ b. Affirmer offers the Work as-is and makes no representations or -+ warranties of any kind concerning the Work, express, implied, -+ statutory or otherwise, including without limitation warranties of -+ title, merchantability, fitness for a particular purpose, non -+ infringement, or the absence of latent or other defects, accuracy, or -+ the present or absence of errors, whether or not discoverable, all to -+ the greatest extent permissible under applicable law. -+ c. Affirmer disclaims responsibility for clearing rights of other persons -+ that may apply to the Work or any use thereof, including without -+ limitation any person's Copyright and Related Rights in the Work. -+ Further, Affirmer disclaims responsibility for obtaining any necessary -+ consents, permissions or other rights required for any use of the -+ Work. -+ d. Affirmer understands and acknowledges that Creative Commons is not a -+ party to this document and has no duty or obligation with respect to -+ this CC0 or use of the Work. -+ -+-------------------------------------------------------------------------------- -+ -+ Apache License -+ Version 2.0, January 2004 -+ http://www.apache.org/licenses/ -+ -+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -+ -+ 1. Definitions. -+ -+ "License" shall mean the terms and conditions for use, reproduction, -+ and distribution as defined by Sections 1 through 9 of this document. -+ -+ "Licensor" shall mean the copyright owner or entity authorized by -+ the copyright owner that is granting the License. -+ -+ "Legal Entity" shall mean the union of the acting entity and all -+ other entities that control, are controlled by, or are under common -+ control with that entity. For the purposes of this definition, -+ "control" means (i) the power, direct or indirect, to cause the -+ direction or management of such entity, whether by contract or -+ otherwise, or (ii) ownership of fifty percent (50%) or more of the -+ outstanding shares, or (iii) beneficial ownership of such entity. -+ -+ "You" (or "Your") shall mean an individual or Legal Entity -+ exercising permissions granted by this License. -+ -+ "Source" form shall mean the preferred form for making modifications, -+ including but not limited to software source code, documentation -+ source, and configuration files. -+ -+ "Object" form shall mean any form resulting from mechanical -+ transformation or translation of a Source form, including but -+ not limited to compiled object code, generated documentation, -+ and conversions to other media types. -+ -+ "Work" shall mean the work of authorship, whether in Source or -+ Object form, made available under the License, as indicated by a -+ copyright notice that is included in or attached to the work -+ (an example is provided in the Appendix below). -+ -+ "Derivative Works" shall mean any work, whether in Source or Object -+ form, that is based on (or derived from) the Work and for which the -+ editorial revisions, annotations, elaborations, or other modifications -+ represent, as a whole, an original work of authorship. For the purposes -+ of this License, Derivative Works shall not include works that remain -+ separable from, or merely link (or bind by name) to the interfaces of, -+ the Work and Derivative Works thereof. -+ -+ "Contribution" shall mean any work of authorship, including -+ the original version of the Work and any modifications or additions -+ to that Work or Derivative Works thereof, that is intentionally -+ submitted to Licensor for inclusion in the Work by the copyright owner -+ or by an individual or Legal Entity authorized to submit on behalf of -+ the copyright owner. For the purposes of this definition, "submitted" -+ means any form of electronic, verbal, or written communication sent -+ to the Licensor or its representatives, including but not limited to -+ communication on electronic mailing lists, source code control systems, -+ and issue tracking systems that are managed by, or on behalf of, the -+ Licensor for the purpose of discussing and improving the Work, but -+ excluding communication that is conspicuously marked or otherwise -+ designated in writing by the copyright owner as "Not a Contribution." -+ -+ "Contributor" shall mean Licensor and any individual or Legal Entity -+ on behalf of whom a Contribution has been received by Licensor and -+ subsequently incorporated within the Work. -+ -+ 2. Grant of Copyright License. Subject to the terms and conditions of -+ this License, each Contributor hereby grants to You a perpetual, -+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable -+ copyright license to reproduce, prepare Derivative Works of, -+ publicly display, publicly perform, sublicense, and distribute the -+ Work and such Derivative Works in Source or Object form. -+ -+ 3. Grant of Patent License. Subject to the terms and conditions of -+ this License, each Contributor hereby grants to You a perpetual, -+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable -+ (except as stated in this section) patent license to make, have made, -+ use, offer to sell, sell, import, and otherwise transfer the Work, -+ where such license applies only to those patent claims licensable -+ by such Contributor that are necessarily infringed by their -+ Contribution(s) alone or by combination of their Contribution(s) -+ with the Work to which such Contribution(s) was submitted. If You -+ institute patent litigation against any entity (including a -+ cross-claim or counterclaim in a lawsuit) alleging that the Work -+ or a Contribution incorporated within the Work constitutes direct -+ or contributory patent infringement, then any patent licenses -+ granted to You under this License for that Work shall terminate -+ as of the date such litigation is filed. -+ -+ 4. Redistribution. You may reproduce and distribute copies of the -+ Work or Derivative Works thereof in any medium, with or without -+ modifications, and in Source or Object form, provided that You -+ meet the following conditions: -+ -+ (a) You must give any other recipients of the Work or -+ Derivative Works a copy of this License; and -+ -+ (b) You must cause any modified files to carry prominent notices -+ stating that You changed the files; and -+ -+ (c) You must retain, in the Source form of any Derivative Works -+ that You distribute, all copyright, patent, trademark, and -+ attribution notices from the Source form of the Work, -+ excluding those notices that do not pertain to any part of -+ the Derivative Works; and -+ -+ (d) If the Work includes a "NOTICE" text file as part of its -+ distribution, then any Derivative Works that You distribute must -+ include a readable copy of the attribution notices contained -+ within such NOTICE file, excluding those notices that do not -+ pertain to any part of the Derivative Works, in at least one -+ of the following places: within a NOTICE text file distributed -+ as part of the Derivative Works; within the Source form or -+ documentation, if provided along with the Derivative Works; or, -+ within a display generated by the Derivative Works, if and -+ wherever such third-party notices normally appear. The contents -+ of the NOTICE file are for informational purposes only and -+ do not modify the License. You may add Your own attribution -+ notices within Derivative Works that You distribute, alongside -+ or as an addendum to the NOTICE text from the Work, provided -+ that such additional attribution notices cannot be construed -+ as modifying the License. -+ -+ You may add Your own copyright statement to Your modifications and -+ may provide additional or different license terms and conditions -+ for use, reproduction, or distribution of Your modifications, or -+ for any such Derivative Works as a whole, provided Your use, -+ reproduction, and distribution of the Work otherwise complies with -+ the conditions stated in this License. -+ -+ 5. Submission of Contributions. Unless You explicitly state otherwise, -+ any Contribution intentionally submitted for inclusion in the Work -+ by You to the Licensor shall be under the terms and conditions of -+ this License, without any additional terms or conditions. -+ Notwithstanding the above, nothing herein shall supersede or modify -+ the terms of any separate license agreement you may have executed -+ with Licensor regarding such Contributions. -+ -+ 6. Trademarks. This License does not grant permission to use the trade -+ names, trademarks, service marks, or product names of the Licensor, -+ except as required for reasonable and customary use in describing the -+ origin of the Work and reproducing the content of the NOTICE file. -+ -+ 7. Disclaimer of Warranty. Unless required by applicable law or -+ agreed to in writing, Licensor provides the Work (and each -+ Contributor provides its Contributions) on an "AS IS" BASIS, -+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -+ implied, including, without limitation, any warranties or conditions -+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A -+ PARTICULAR PURPOSE. You are solely responsible for determining the -+ appropriateness of using or redistributing the Work and assume any -+ risks associated with Your exercise of permissions under this License. -+ -+ 8. Limitation of Liability. In no event and under no legal theory, -+ whether in tort (including negligence), contract, or otherwise, -+ unless required by applicable law (such as deliberate and grossly -+ negligent acts) or agreed to in writing, shall any Contributor be -+ liable to You for damages, including any direct, indirect, special, -+ incidental, or consequential damages of any character arising as a -+ result of this License or out of the use or inability to use the -+ Work (including but not limited to damages for loss of goodwill, -+ work stoppage, computer failure or malfunction, or any and all -+ other commercial damages or losses), even if such Contributor -+ has been advised of the possibility of such damages. -+ -+ 9. Accepting Warranty or Additional Liability. While redistributing -+ the Work or Derivative Works thereof, You may choose to offer, -+ and charge a fee for, acceptance of support, warranty, indemnity, -+ or other liability obligations and/or rights consistent with this -+ License. However, in accepting such obligations, You may act only -+ on Your own behalf and on Your sole responsibility, not on behalf -+ of any other Contributor, and only if You agree to indemnify, -+ defend, and hold each Contributor harmless for any liability -+ incurred by, or claims asserted against, such Contributor by reason -+ of your accepting any such warranty or additional liability. -diff --git a/grub-core/lib/argon2/argon2.c b/grub-core/lib/argon2/argon2.c -new file mode 100644 -index 000000000..49532fe80 ---- /dev/null -+++ b/grub-core/lib/argon2/argon2.c -@@ -0,0 +1,232 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#include <grub/dl.h> -+ -+#include "argon2.h" -+#include "core.h" -+ -+GRUB_MOD_LICENSE ("CC0"); -+ -+static int argon2_ctx(argon2_context *context, argon2_type type) { -+ /* 1. Validate all inputs */ -+ int result = validate_inputs(context); -+ grub_uint32_t memory_blocks, segment_length; -+ argon2_instance_t instance; -+ -+ if (ARGON2_OK != result) { -+ return result; -+ } -+ -+ if (Argon2_d != type && Argon2_i != type && Argon2_id != type) { -+ return ARGON2_INCORRECT_TYPE; -+ } -+ -+ /* 2. Align memory size */ -+ /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */ -+ memory_blocks = context->m_cost; -+ -+ if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) { -+ memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes; -+ } -+ -+ segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS); -+ /* Ensure that all segments have equal length */ -+ memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS); -+ -+ instance.version = context->version; -+ instance.memory = NULL; -+ instance.passes = context->t_cost; -+ instance.memory_blocks = memory_blocks; -+ instance.segment_length = segment_length; -+ instance.lane_length = segment_length * ARGON2_SYNC_POINTS; -+ instance.lanes = context->lanes; -+ instance.threads = context->threads; -+ instance.type = type; -+ -+ if (instance.threads > instance.lanes) { -+ instance.threads = instance.lanes; -+ } -+ -+ /* 3. Initialization: Hashing inputs, allocating memory, filling first -+ * blocks -+ */ -+ result = initialize(&instance, context); -+ -+ if (ARGON2_OK != result) { -+ return result; -+ } -+ -+ /* 4. Filling memory */ -+ result = fill_memory_blocks(&instance); -+ -+ if (ARGON2_OK != result) { -+ return result; -+ } -+ /* 5. Finalization */ -+ finalize(context, &instance); -+ -+ return ARGON2_OK; -+} -+ -+int argon2_hash(const grub_uint32_t t_cost, const grub_uint32_t m_cost, -+ const grub_uint32_t parallelism, const void *pwd, -+ const grub_size_t pwdlen, const void *salt, const grub_size_t saltlen, -+ void *hash, const grub_size_t hashlen, argon2_type type, -+ const grub_uint32_t version){ -+ -+ argon2_context context; -+ int result; -+ grub_uint8_t *out; -+ -+ if (pwdlen > ARGON2_MAX_PWD_LENGTH) { -+ return ARGON2_PWD_TOO_LONG; -+ } -+ -+ if (saltlen > ARGON2_MAX_SALT_LENGTH) { -+ return ARGON2_SALT_TOO_LONG; -+ } -+ -+ if (hashlen > ARGON2_MAX_OUTLEN) { -+ return ARGON2_OUTPUT_TOO_LONG; -+ } -+ -+ if (hashlen < ARGON2_MIN_OUTLEN) { -+ return ARGON2_OUTPUT_TOO_SHORT; -+ } -+ -+ out = grub_malloc(hashlen); -+ if (!out) { -+ return ARGON2_MEMORY_ALLOCATION_ERROR; -+ } -+ -+ context.out = (grub_uint8_t *)out; -+ context.outlen = (grub_uint32_t)hashlen; -+ context.pwd = CONST_CAST(grub_uint8_t *)pwd; -+ context.pwdlen = (grub_uint32_t)pwdlen; -+ context.salt = CONST_CAST(grub_uint8_t *)salt; -+ context.saltlen = (grub_uint32_t)saltlen; -+ context.secret = NULL; -+ context.secretlen = 0; -+ context.ad = NULL; -+ context.adlen = 0; -+ context.t_cost = t_cost; -+ context.m_cost = m_cost; -+ context.lanes = parallelism; -+ context.threads = parallelism; -+ context.allocate_cbk = NULL; -+ context.grub_free_cbk = NULL; -+ context.flags = ARGON2_DEFAULT_FLAGS; -+ context.version = version; -+ -+ result = argon2_ctx(&context, type); -+ -+ if (result != ARGON2_OK) { -+ clear_internal_memory(out, hashlen); -+ grub_free(out); -+ return result; -+ } -+ -+ /* if raw hash requested, write it */ -+ if (hash) { -+ grub_memcpy(hash, out, hashlen); -+ } -+ -+ clear_internal_memory(out, hashlen); -+ grub_free(out); -+ -+ return ARGON2_OK; -+} -+ -+const char *argon2_error_message(int error_code) { -+ switch (error_code) { -+ case ARGON2_OK: -+ return "OK"; -+ case ARGON2_OUTPUT_PTR_NULL: -+ return "Output pointer is NULL"; -+ case ARGON2_OUTPUT_TOO_SHORT: -+ return "Output is too short"; -+ case ARGON2_OUTPUT_TOO_LONG: -+ return "Output is too long"; -+ case ARGON2_PWD_TOO_SHORT: -+ return "Password is too short"; -+ case ARGON2_PWD_TOO_LONG: -+ return "Password is too long"; -+ case ARGON2_SALT_TOO_SHORT: -+ return "Salt is too short"; -+ case ARGON2_SALT_TOO_LONG: -+ return "Salt is too long"; -+ case ARGON2_AD_TOO_SHORT: -+ return "Associated data is too short"; -+ case ARGON2_AD_TOO_LONG: -+ return "Associated data is too long"; -+ case ARGON2_SECRET_TOO_SHORT: -+ return "Secret is too short"; -+ case ARGON2_SECRET_TOO_LONG: -+ return "Secret is too long"; -+ case ARGON2_TIME_TOO_SMALL: -+ return "Time cost is too small"; -+ case ARGON2_TIME_TOO_LARGE: -+ return "Time cost is too large"; -+ case ARGON2_MEMORY_TOO_LITTLE: -+ return "Memory cost is too small"; -+ case ARGON2_MEMORY_TOO_MUCH: -+ return "Memory cost is too large"; -+ case ARGON2_LANES_TOO_FEW: -+ return "Too few lanes"; -+ case ARGON2_LANES_TOO_MANY: -+ return "Too many lanes"; -+ case ARGON2_PWD_PTR_MISMATCH: -+ return "Password pointer is NULL, but password length is not 0"; -+ case ARGON2_SALT_PTR_MISMATCH: -+ return "Salt pointer is NULL, but salt length is not 0"; -+ case ARGON2_SECRET_PTR_MISMATCH: -+ return "Secret pointer is NULL, but secret length is not 0"; -+ case ARGON2_AD_PTR_MISMATCH: -+ return "Associated data pointer is NULL, but ad length is not 0"; -+ case ARGON2_MEMORY_ALLOCATION_ERROR: -+ return "Memory allocation error"; -+ case ARGON2_FREE_MEMORY_CBK_NULL: -+ return "The grub_free memory callback is NULL"; -+ case ARGON2_ALLOCATE_MEMORY_CBK_NULL: -+ return "The allocate memory callback is NULL"; -+ case ARGON2_INCORRECT_PARAMETER: -+ return "Argon2_Context context is NULL"; -+ case ARGON2_INCORRECT_TYPE: -+ return "There is no such version of Argon2"; -+ case ARGON2_OUT_PTR_MISMATCH: -+ return "Output pointer mismatch"; -+ case ARGON2_THREADS_TOO_FEW: -+ return "Not enough threads"; -+ case ARGON2_THREADS_TOO_MANY: -+ return "Too many threads"; -+ case ARGON2_MISSING_ARGS: -+ return "Missing arguments"; -+ case ARGON2_ENCODING_FAIL: -+ return "Encoding failed"; -+ case ARGON2_DECODING_FAIL: -+ return "Decoding failed"; -+ case ARGON2_THREAD_FAIL: -+ return "Threading failure"; -+ case ARGON2_DECODING_LENGTH_FAIL: -+ return "Some of encoded parameters are too long or too short"; -+ case ARGON2_VERIFY_MISMATCH: -+ return "The password does not match the supplied hash"; -+ default: -+ return "Unknown error code"; -+ } -+} -diff --git a/grub-core/lib/argon2/argon2.h b/grub-core/lib/argon2/argon2.h -new file mode 100644 -index 000000000..129f7efbd ---- /dev/null -+++ b/grub-core/lib/argon2/argon2.h -@@ -0,0 +1,264 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#ifndef ARGON2_H -+#define ARGON2_H -+ -+#include <grub/misc.h> -+#include <grub/mm.h> -+ -+#if defined(__cplusplus) -+extern "C" { -+#endif -+ -+/* Symbols visibility control */ -+#ifdef A2_VISCTL -+#define ARGON2_PUBLIC __attribute__((visibility("default"))) -+#define ARGON2_LOCAL __attribute__ ((visibility ("hidden"))) -+#elif defined(_MSC_VER) -+#define ARGON2_PUBLIC __declspec(dllexport) -+#define ARGON2_LOCAL -+#else -+#define ARGON2_PUBLIC -+#define ARGON2_LOCAL -+#endif -+ -+/* -+ * Argon2 input parameter restrictions -+ */ -+ -+/* Minimum and maximum number of lanes (degree of parallelism) */ -+#define ARGON2_MIN_LANES GRUB_UINT32_C(1) -+#define ARGON2_MAX_LANES GRUB_UINT32_C(0xFFFFFF) -+ -+/* Minimum and maximum number of threads */ -+#define ARGON2_MIN_THREADS GRUB_UINT32_C(1) -+#define ARGON2_MAX_THREADS GRUB_UINT32_C(0xFFFFFF) -+ -+/* Number of synchronization points between lanes per pass */ -+#define ARGON2_SYNC_POINTS GRUB_UINT32_C(4) -+ -+/* Minimum and maximum digest size in bytes */ -+#define ARGON2_MIN_OUTLEN GRUB_UINT32_C(4) -+#define ARGON2_MAX_OUTLEN GRUB_UINT32_C(0xFFFFFFFF) -+ -+/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */ -+#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */ -+ -+#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b)) -+/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */ -+#define ARGON2_MAX_MEMORY_BITS \ -+ ARGON2_MIN(GRUB_UINT32_C(32), (sizeof(void *) * GRUB_CHAR_BIT - 10 - 1)) -+#define ARGON2_MAX_MEMORY \ -+ ARGON2_MIN(GRUB_UINT32_C(0xFFFFFFFF), GRUB_UINT64_C(1) << ARGON2_MAX_MEMORY_BITS) -+ -+/* Minimum and maximum number of passes */ -+#define ARGON2_MIN_TIME GRUB_UINT32_C(1) -+#define ARGON2_MAX_TIME GRUB_UINT32_C(0xFFFFFFFF) -+ -+/* Minimum and maximum password length in bytes */ -+#define ARGON2_MIN_PWD_LENGTH GRUB_UINT32_C(0) -+#define ARGON2_MAX_PWD_LENGTH GRUB_UINT32_C(0xFFFFFFFF) -+ -+/* Minimum and maximum associated data length in bytes */ -+#define ARGON2_MIN_AD_LENGTH GRUB_UINT32_C(0) -+#define ARGON2_MAX_AD_LENGTH GRUB_UINT32_C(0xFFFFFFFF) -+ -+/* Minimum and maximum salt length in bytes */ -+#define ARGON2_MIN_SALT_LENGTH GRUB_UINT32_C(8) -+#define ARGON2_MAX_SALT_LENGTH GRUB_UINT32_C(0xFFFFFFFF) -+ -+/* Minimum and maximum key length in bytes */ -+#define ARGON2_MIN_SECRET GRUB_UINT32_C(0) -+#define ARGON2_MAX_SECRET GRUB_UINT32_C(0xFFFFFFFF) -+ -+/* Flags to determine which fields are securely wiped (default = no wipe). */ -+#define ARGON2_DEFAULT_FLAGS GRUB_UINT32_C(0) -+#define ARGON2_FLAG_CLEAR_PASSWORD (GRUB_UINT32_C(1) << 0) -+#define ARGON2_FLAG_CLEAR_SECRET (GRUB_UINT32_C(1) << 1) -+ -+/* Global flag to determine if we are wiping internal memory buffers. This flag -+ * is defined in core.c and defaults to 1 (wipe internal memory). */ -+extern int FLAG_clear_internal_memory; -+ -+/* Error codes */ -+typedef enum Argon2_ErrorCodes { -+ ARGON2_OK = 0, -+ -+ ARGON2_OUTPUT_PTR_NULL = -1, -+ -+ ARGON2_OUTPUT_TOO_SHORT = -2, -+ ARGON2_OUTPUT_TOO_LONG = -3, -+ -+ ARGON2_PWD_TOO_SHORT = -4, -+ ARGON2_PWD_TOO_LONG = -5, -+ -+ ARGON2_SALT_TOO_SHORT = -6, -+ ARGON2_SALT_TOO_LONG = -7, -+ -+ ARGON2_AD_TOO_SHORT = -8, -+ ARGON2_AD_TOO_LONG = -9, -+ -+ ARGON2_SECRET_TOO_SHORT = -10, -+ ARGON2_SECRET_TOO_LONG = -11, -+ -+ ARGON2_TIME_TOO_SMALL = -12, -+ ARGON2_TIME_TOO_LARGE = -13, -+ -+ ARGON2_MEMORY_TOO_LITTLE = -14, -+ ARGON2_MEMORY_TOO_MUCH = -15, -+ -+ ARGON2_LANES_TOO_FEW = -16, -+ ARGON2_LANES_TOO_MANY = -17, -+ -+ ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */ -+ ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */ -+ ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */ -+ ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */ -+ -+ ARGON2_MEMORY_ALLOCATION_ERROR = -22, -+ -+ ARGON2_FREE_MEMORY_CBK_NULL = -23, -+ ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24, -+ -+ ARGON2_INCORRECT_PARAMETER = -25, -+ ARGON2_INCORRECT_TYPE = -26, -+ -+ ARGON2_OUT_PTR_MISMATCH = -27, -+ -+ ARGON2_THREADS_TOO_FEW = -28, -+ ARGON2_THREADS_TOO_MANY = -29, -+ -+ ARGON2_MISSING_ARGS = -30, -+ -+ ARGON2_ENCODING_FAIL = -31, -+ -+ ARGON2_DECODING_FAIL = -32, -+ -+ ARGON2_THREAD_FAIL = -33, -+ -+ ARGON2_DECODING_LENGTH_FAIL = -34, -+ -+ ARGON2_VERIFY_MISMATCH = -35 -+} argon2_error_codes; -+ -+/* Memory allocator types --- for external allocation */ -+typedef int (*allocate_fptr)(grub_uint8_t **memory, grub_size_t bytes_to_allocate); -+typedef void (*deallocate_fptr)(grub_uint8_t *memory, grub_size_t bytes_to_allocate); -+ -+/* Argon2 external data structures */ -+ -+/* -+ ***** -+ * Context: structure to hold Argon2 inputs: -+ * output array and its length, -+ * password and its length, -+ * salt and its length, -+ * secret and its length, -+ * associated data and its length, -+ * number of passes, amount of used memory (in KBytes, can be rounded up a bit) -+ * number of parallel threads that will be run. -+ * All the parameters above affect the output hash value. -+ * Additionally, two function pointers can be provided to allocate and -+ * deallocate the memory (if NULL, memory will be allocated internally). -+ * Also, three flags indicate whether to erase password, secret as soon as they -+ * are pre-hashed (and thus not needed anymore), and the entire memory -+ ***** -+ * Simplest situation: you have output array out[8], password is stored in -+ * pwd[32], salt is stored in salt[16], you do not have keys nor associated -+ * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with -+ * 4 parallel lanes. -+ * You want to erase the password, but you're OK with last pass not being -+ * erased. You want to use the default memory allocator. -+ * Then you initialize: -+ Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false) -+ */ -+typedef struct Argon2_Context { -+ grub_uint8_t *out; /* output array */ -+ grub_uint32_t outlen; /* digest length */ -+ -+ grub_uint8_t *pwd; /* password array */ -+ grub_uint32_t pwdlen; /* password length */ -+ -+ grub_uint8_t *salt; /* salt array */ -+ grub_uint32_t saltlen; /* salt length */ -+ -+ grub_uint8_t *secret; /* key array */ -+ grub_uint32_t secretlen; /* key length */ -+ -+ grub_uint8_t *ad; /* associated data array */ -+ grub_uint32_t adlen; /* associated data length */ -+ -+ grub_uint32_t t_cost; /* number of passes */ -+ grub_uint32_t m_cost; /* amount of memory requested (KB) */ -+ grub_uint32_t lanes; /* number of lanes */ -+ grub_uint32_t threads; /* maximum number of threads */ -+ -+ grub_uint32_t version; /* version number */ -+ -+ allocate_fptr allocate_cbk; /* pointer to memory allocator */ -+ deallocate_fptr grub_free_cbk; /* pointer to memory deallocator */ -+ -+ grub_uint32_t flags; /* array of bool options */ -+} argon2_context; -+ -+/* Argon2 primitive type */ -+typedef enum Argon2_type { -+ Argon2_d = 0, -+ Argon2_i = 1, -+ Argon2_id = 2 -+} argon2_type; -+ -+/* Version of the algorithm */ -+typedef enum Argon2_version { -+ ARGON2_VERSION_10 = 0x10, -+ ARGON2_VERSION_13 = 0x13, -+ ARGON2_VERSION_NUMBER = ARGON2_VERSION_13 -+} argon2_version; -+ -+/** -+ * Hashes a password with Argon2, producing a raw hash at @hash -+ * @param t_cost Number of iterations -+ * @param m_cost Sets memory usage to m_cost kibibytes -+ * @param parallelism Number of threads and compute lanes -+ * @param pwd Pointer to password -+ * @param pwdlen Password size in bytes -+ * @param salt Pointer to salt -+ * @param saltlen Salt size in bytes -+ * @param hash Buffer where to write the raw hash - updated by the function -+ * @param hashlen Desired length of the hash in bytes -+ * @pre Different parallelism levels will give different results -+ * @pre Returns ARGON2_OK if successful -+ */ -+ARGON2_PUBLIC int argon2_hash(const grub_uint32_t t_cost, const grub_uint32_t m_cost, -+ const grub_uint32_t parallelism, const void *pwd, -+ const grub_size_t pwdlen, const void *salt, -+ const grub_size_t saltlen, void *hash, -+ const grub_size_t hashlen, argon2_type type, -+ const grub_uint32_t version); -+ -+/** -+ * Get the associated error message for given error code -+ * @return The error message associated with the given error code -+ */ -+ARGON2_PUBLIC const char *argon2_error_message(int error_code); -+ -+#if defined(__cplusplus) -+} -+#endif -+ -+#endif -diff --git a/grub-core/lib/argon2/blake2/blake2-impl.h b/grub-core/lib/argon2/blake2/blake2-impl.h -new file mode 100644 -index 000000000..3a795680b ---- /dev/null -+++ b/grub-core/lib/argon2/blake2/blake2-impl.h -@@ -0,0 +1,151 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#ifndef PORTABLE_BLAKE2_IMPL_H -+#define PORTABLE_BLAKE2_IMPL_H -+ -+#if defined(_MSC_VER) -+#define BLAKE2_INLINE __inline -+#elif defined(__GNUC__) || defined(__clang__) -+#define BLAKE2_INLINE __inline__ -+#else -+#define BLAKE2_INLINE -+#endif -+ -+/* Argon2 Team - Begin Code */ -+/* -+ Not an exhaustive list, but should cover the majority of modern platforms -+ Additionally, the code will always be correct---this is only a performance -+ tweak. -+*/ -+#if (defined(__BYTE_ORDER__) && \ -+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \ -+ defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \ -+ defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) || \ -+ defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || \ -+ defined(_M_ARM) -+#define NATIVE_LITTLE_ENDIAN -+#endif -+/* Argon2 Team - End Code */ -+ -+static BLAKE2_INLINE grub_uint32_t load32(const void *src) { -+#if defined(NATIVE_LITTLE_ENDIAN) -+ grub_uint32_t w; -+ grub_memcpy(&w, src, sizeof w); -+ return w; -+#else -+ const grub_uint8_t *p = (const grub_uint8_t *)src; -+ grub_uint32_t w = *p++; -+ w |= (grub_uint32_t)(*p++) << 8; -+ w |= (grub_uint32_t)(*p++) << 16; -+ w |= (grub_uint32_t)(*p++) << 24; -+ return w; -+#endif -+} -+ -+static BLAKE2_INLINE grub_uint64_t load64(const void *src) { -+#if defined(NATIVE_LITTLE_ENDIAN) -+ grub_uint64_t w; -+ grub_memcpy(&w, src, sizeof w); -+ return w; -+#else -+ const grub_uint8_t *p = (const grub_uint8_t *)src; -+ grub_uint64_t w = *p++; -+ w |= (grub_uint64_t)(*p++) << 8; -+ w |= (grub_uint64_t)(*p++) << 16; -+ w |= (grub_uint64_t)(*p++) << 24; -+ w |= (grub_uint64_t)(*p++) << 32; -+ w |= (grub_uint64_t)(*p++) << 40; -+ w |= (grub_uint64_t)(*p++) << 48; -+ w |= (grub_uint64_t)(*p++) << 56; -+ return w; -+#endif -+} -+ -+static BLAKE2_INLINE void store32(void *dst, grub_uint32_t w) { -+#if defined(NATIVE_LITTLE_ENDIAN) -+ grub_memcpy(dst, &w, sizeof w); -+#else -+ grub_uint8_t *p = (grub_uint8_t *)dst; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+#endif -+} -+ -+static BLAKE2_INLINE void store64(void *dst, grub_uint64_t w) { -+#if defined(NATIVE_LITTLE_ENDIAN) -+ grub_memcpy(dst, &w, sizeof w); -+#else -+ grub_uint8_t *p = (grub_uint8_t *)dst; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+#endif -+} -+ -+static BLAKE2_INLINE grub_uint64_t load48(const void *src) { -+ const grub_uint8_t *p = (const grub_uint8_t *)src; -+ grub_uint64_t w = *p++; -+ w |= (grub_uint64_t)(*p++) << 8; -+ w |= (grub_uint64_t)(*p++) << 16; -+ w |= (grub_uint64_t)(*p++) << 24; -+ w |= (grub_uint64_t)(*p++) << 32; -+ w |= (grub_uint64_t)(*p++) << 40; -+ return w; -+} -+ -+static BLAKE2_INLINE void store48(void *dst, grub_uint64_t w) { -+ grub_uint8_t *p = (grub_uint8_t *)dst; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+ w >>= 8; -+ *p++ = (grub_uint8_t)w; -+} -+ -+static BLAKE2_INLINE grub_uint32_t rotr32(const grub_uint32_t w, const unsigned c) { -+ return (w >> c) | (w << (32 - c)); -+} -+ -+static BLAKE2_INLINE grub_uint64_t rotr64(const grub_uint64_t w, const unsigned c) { -+ return (w >> c) | (w << (64 - c)); -+} -+ -+#endif -diff --git a/grub-core/lib/argon2/blake2/blake2.h b/grub-core/lib/argon2/blake2/blake2.h -new file mode 100644 -index 000000000..4e8efeb22 ---- /dev/null -+++ b/grub-core/lib/argon2/blake2/blake2.h -@@ -0,0 +1,89 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#ifndef PORTABLE_BLAKE2_H -+#define PORTABLE_BLAKE2_H -+ -+#include "../argon2.h" -+ -+#if defined(__cplusplus) -+extern "C" { -+#endif -+ -+enum blake2b_constant { -+ BLAKE2B_BLOCKBYTES = 128, -+ BLAKE2B_OUTBYTES = 64, -+ BLAKE2B_KEYBYTES = 64, -+ BLAKE2B_SALTBYTES = 16, -+ BLAKE2B_PERSONALBYTES = 16 -+}; -+ -+#pragma pack(push, 1) -+typedef struct __blake2b_param { -+ grub_uint8_t digest_length; /* 1 */ -+ grub_uint8_t key_length; /* 2 */ -+ grub_uint8_t fanout; /* 3 */ -+ grub_uint8_t depth; /* 4 */ -+ grub_uint32_t leaf_length; /* 8 */ -+ grub_uint64_t node_offset; /* 16 */ -+ grub_uint8_t node_depth; /* 17 */ -+ grub_uint8_t inner_length; /* 18 */ -+ grub_uint8_t reserved[14]; /* 32 */ -+ grub_uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ -+ grub_uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ -+} blake2b_param; -+#pragma pack(pop) -+ -+typedef struct __blake2b_state { -+ grub_uint64_t h[8]; -+ grub_uint64_t t[2]; -+ grub_uint64_t f[2]; -+ grub_uint8_t buf[BLAKE2B_BLOCKBYTES]; -+ unsigned buflen; -+ unsigned outlen; -+ grub_uint8_t last_node; -+} blake2b_state; -+ -+/* Ensure param structs have not been wrongly padded */ -+/* Poor man's static_assert */ -+enum { -+ blake2_size_check_0 = 1 / !!(GRUB_CHAR_BIT == 8), -+ blake2_size_check_2 = -+ 1 / !!(sizeof(blake2b_param) == sizeof(grub_uint64_t) * GRUB_CHAR_BIT) -+}; -+ -+/* Streaming API */ -+ARGON2_LOCAL int blake2b_init(blake2b_state *S, grub_size_t outlen); -+ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, grub_size_t outlen, const void *key, -+ grub_size_t keylen); -+ARGON2_LOCAL int blake2b_init_param(blake2b_state *S, const blake2b_param *P); -+ARGON2_LOCAL int blake2b_update(blake2b_state *S, const void *in, grub_size_t inlen); -+ARGON2_LOCAL int blake2b_final(blake2b_state *S, void *out, grub_size_t outlen); -+ -+/* Simple API */ -+ARGON2_LOCAL int blake2b(void *out, grub_size_t outlen, const void *in, grub_size_t inlen, -+ const void *key, grub_size_t keylen); -+ -+/* Argon2 Team - Begin Code */ -+ARGON2_LOCAL int blake2b_long(void *out, grub_size_t outlen, const void *in, grub_size_t inlen); -+/* Argon2 Team - End Code */ -+ -+#if defined(__cplusplus) -+} -+#endif -+ -+#endif -diff --git a/grub-core/lib/argon2/blake2/blake2b.c b/grub-core/lib/argon2/blake2/blake2b.c -new file mode 100644 -index 000000000..53abd7bef ---- /dev/null -+++ b/grub-core/lib/argon2/blake2/blake2b.c -@@ -0,0 +1,388 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#include "blake2.h" -+#include "blake2-impl.h" -+ -+static const grub_uint64_t blake2b_IV[8] = { -+ GRUB_UINT64_C(0x6a09e667f3bcc908), GRUB_UINT64_C(0xbb67ae8584caa73b), -+ GRUB_UINT64_C(0x3c6ef372fe94f82b), GRUB_UINT64_C(0xa54ff53a5f1d36f1), -+ GRUB_UINT64_C(0x510e527fade682d1), GRUB_UINT64_C(0x9b05688c2b3e6c1f), -+ GRUB_UINT64_C(0x1f83d9abfb41bd6b), GRUB_UINT64_C(0x5be0cd19137e2179)}; -+ -+static const unsigned int blake2b_sigma[12][16] = { -+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, -+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, -+ {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, -+ {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, -+ {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, -+ {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, -+ {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, -+ {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, -+ {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, -+ {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, -+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, -+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, -+}; -+ -+void clear_internal_memory(void *v, grub_size_t n); -+ -+static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) { -+ S->f[1] = (grub_uint64_t)-1; -+} -+ -+static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) { -+ if (S->last_node) { -+ blake2b_set_lastnode(S); -+ } -+ S->f[0] = (grub_uint64_t)-1; -+} -+ -+static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S, -+ grub_uint64_t inc) { -+ S->t[0] += inc; -+ S->t[1] += (S->t[0] < inc); -+} -+ -+static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) { -+ clear_internal_memory(S, sizeof(*S)); /* wipe */ -+ blake2b_set_lastblock(S); /* invalidate for further use */ -+} -+ -+static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) { -+ grub_memset(S, 0, sizeof(*S)); -+ grub_memcpy(S->h, blake2b_IV, sizeof(S->h)); -+} -+ -+int blake2b_init_param(blake2b_state *S, const blake2b_param *P) { -+ const unsigned char *p = (const unsigned char *)P; -+ unsigned int i; -+ -+ if (NULL == P || NULL == S) { -+ return -1; -+ } -+ -+ blake2b_init0(S); -+ /* IV XOR Parameter Block */ -+ for (i = 0; i < 8; ++i) { -+ S->h[i] ^= load64(&p[i * sizeof(S->h[i])]); -+ } -+ S->outlen = P->digest_length; -+ return 0; -+} -+ -+/* Sequential blake2b initialization */ -+int blake2b_init(blake2b_state *S, grub_size_t outlen) { -+ blake2b_param P; -+ -+ if (S == NULL) { -+ return -1; -+ } -+ -+ if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { -+ blake2b_invalidate_state(S); -+ return -1; -+ } -+ -+ /* Setup Parameter Block for unkeyed BLAKE2 */ -+ P.digest_length = (grub_uint8_t)outlen; -+ P.key_length = 0; -+ P.fanout = 1; -+ P.depth = 1; -+ P.leaf_length = 0; -+ P.node_offset = 0; -+ P.node_depth = 0; -+ P.inner_length = 0; -+ grub_memset(P.reserved, 0, sizeof(P.reserved)); -+ grub_memset(P.salt, 0, sizeof(P.salt)); -+ grub_memset(P.personal, 0, sizeof(P.personal)); -+ -+ return blake2b_init_param(S, &P); -+} -+ -+int blake2b_init_key(blake2b_state *S, grub_size_t outlen, const void *key, -+ grub_size_t keylen) { -+ blake2b_param P; -+ -+ if (S == NULL) { -+ return -1; -+ } -+ -+ if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { -+ blake2b_invalidate_state(S); -+ return -1; -+ } -+ -+ if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) { -+ blake2b_invalidate_state(S); -+ return -1; -+ } -+ -+ /* Setup Parameter Block for keyed BLAKE2 */ -+ P.digest_length = (grub_uint8_t)outlen; -+ P.key_length = (grub_uint8_t)keylen; -+ P.fanout = 1; -+ P.depth = 1; -+ P.leaf_length = 0; -+ P.node_offset = 0; -+ P.node_depth = 0; -+ P.inner_length = 0; -+ grub_memset(P.reserved, 0, sizeof(P.reserved)); -+ grub_memset(P.salt, 0, sizeof(P.salt)); -+ grub_memset(P.personal, 0, sizeof(P.personal)); -+ -+ if (blake2b_init_param(S, &P) < 0) { -+ blake2b_invalidate_state(S); -+ return -1; -+ } -+ -+ { -+ grub_uint8_t block[BLAKE2B_BLOCKBYTES]; -+ grub_memset(block, 0, BLAKE2B_BLOCKBYTES); -+ grub_memcpy(block, key, keylen); -+ blake2b_update(S, block, BLAKE2B_BLOCKBYTES); -+ /* Burn the key from stack */ -+ clear_internal_memory(block, BLAKE2B_BLOCKBYTES); -+ } -+ return 0; -+} -+ -+static void blake2b_compress(blake2b_state *S, const grub_uint8_t *block) { -+ grub_uint64_t m[16]; -+ grub_uint64_t v[16]; -+ unsigned int i, r; -+ -+ for (i = 0; i < 16; ++i) { -+ m[i] = load64(block + i * sizeof(m[i])); -+ } -+ -+ for (i = 0; i < 8; ++i) { -+ v[i] = S->h[i]; -+ } -+ -+ v[8] = blake2b_IV[0]; -+ v[9] = blake2b_IV[1]; -+ v[10] = blake2b_IV[2]; -+ v[11] = blake2b_IV[3]; -+ v[12] = blake2b_IV[4] ^ S->t[0]; -+ v[13] = blake2b_IV[5] ^ S->t[1]; -+ v[14] = blake2b_IV[6] ^ S->f[0]; -+ v[15] = blake2b_IV[7] ^ S->f[1]; -+ -+#define G(r, i, a, b, c, d) \ -+ do { \ -+ a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ -+ d = rotr64(d ^ a, 32); \ -+ c = c + d; \ -+ b = rotr64(b ^ c, 24); \ -+ a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ -+ d = rotr64(d ^ a, 16); \ -+ c = c + d; \ -+ b = rotr64(b ^ c, 63); \ -+ } while ((void)0, 0) -+ -+#define ROUND(r) \ -+ do { \ -+ G(r, 0, v[0], v[4], v[8], v[12]); \ -+ G(r, 1, v[1], v[5], v[9], v[13]); \ -+ G(r, 2, v[2], v[6], v[10], v[14]); \ -+ G(r, 3, v[3], v[7], v[11], v[15]); \ -+ G(r, 4, v[0], v[5], v[10], v[15]); \ -+ G(r, 5, v[1], v[6], v[11], v[12]); \ -+ G(r, 6, v[2], v[7], v[8], v[13]); \ -+ G(r, 7, v[3], v[4], v[9], v[14]); \ -+ } while ((void)0, 0) -+ -+ for (r = 0; r < 12; ++r) { -+ ROUND(r); -+ } -+ -+ for (i = 0; i < 8; ++i) { -+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; -+ } -+ -+#undef G -+#undef ROUND -+} -+ -+int blake2b_update(blake2b_state *S, const void *in, grub_size_t inlen) { -+ const grub_uint8_t *pin = (const grub_uint8_t *)in; -+ -+ if (inlen == 0) { -+ return 0; -+ } -+ -+ /* Sanity check */ -+ if (S == NULL || in == NULL) { -+ return -1; -+ } -+ -+ /* Is this a reused state? */ -+ if (S->f[0] != 0) { -+ return -1; -+ } -+ -+ if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) { -+ /* Complete current block */ -+ grub_size_t left = S->buflen; -+ grub_size_t fill = BLAKE2B_BLOCKBYTES - left; -+ grub_memcpy(&S->buf[left], pin, fill); -+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); -+ blake2b_compress(S, S->buf); -+ S->buflen = 0; -+ inlen -= fill; -+ pin += fill; -+ /* Avoid buffer copies when possible */ -+ while (inlen > BLAKE2B_BLOCKBYTES) { -+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); -+ blake2b_compress(S, pin); -+ inlen -= BLAKE2B_BLOCKBYTES; -+ pin += BLAKE2B_BLOCKBYTES; -+ } -+ } -+ grub_memcpy(&S->buf[S->buflen], pin, inlen); -+ S->buflen += (unsigned int)inlen; -+ return 0; -+} -+ -+int blake2b_final(blake2b_state *S, void *out, grub_size_t outlen) { -+ grub_uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; -+ unsigned int i; -+ -+ /* Sanity checks */ -+ if (S == NULL || out == NULL || outlen < S->outlen) { -+ return -1; -+ } -+ -+ /* Is this a reused state? */ -+ if (S->f[0] != 0) { -+ return -1; -+ } -+ -+ blake2b_increment_counter(S, S->buflen); -+ blake2b_set_lastblock(S); -+ grub_memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ -+ blake2b_compress(S, S->buf); -+ -+ for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ -+ store64(buffer + sizeof(S->h[i]) * i, S->h[i]); -+ } -+ -+ grub_memcpy(out, buffer, S->outlen); -+ clear_internal_memory(buffer, sizeof(buffer)); -+ clear_internal_memory(S->buf, sizeof(S->buf)); -+ clear_internal_memory(S->h, sizeof(S->h)); -+ return 0; -+} -+ -+int blake2b(void *out, grub_size_t outlen, const void *in, grub_size_t inlen, -+ const void *key, grub_size_t keylen) { -+ blake2b_state S; -+ int ret = -1; -+ -+ /* Verify parameters */ -+ if (NULL == in && inlen > 0) { -+ goto fail; -+ } -+ -+ if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) { -+ goto fail; -+ } -+ -+ if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) { -+ goto fail; -+ } -+ -+ if (keylen > 0) { -+ if (blake2b_init_key(&S, outlen, key, keylen) < 0) { -+ goto fail; -+ } -+ } else { -+ if (blake2b_init(&S, outlen) < 0) { -+ goto fail; -+ } -+ } -+ -+ if (blake2b_update(&S, in, inlen) < 0) { -+ goto fail; -+ } -+ ret = blake2b_final(&S, out, outlen); -+ -+fail: -+ clear_internal_memory(&S, sizeof(S)); -+ return ret; -+} -+ -+/* Argon2 Team - Begin Code */ -+int blake2b_long(void *pout, grub_size_t outlen, const void *in, grub_size_t inlen) { -+ grub_uint8_t *out = (grub_uint8_t *)pout; -+ blake2b_state blake_state; -+ grub_uint8_t outlen_bytes[sizeof(grub_uint32_t)] = {0}; -+ int ret = -1; -+ -+ if (outlen > GRUB_UINT32_MAX) { -+ goto fail; -+ } -+ -+ /* Ensure little-endian byte order! */ -+ store32(outlen_bytes, (grub_uint32_t)outlen); -+ -+#define TRY(statement) \ -+ do { \ -+ ret = statement; \ -+ if (ret < 0) { \ -+ goto fail; \ -+ } \ -+ } while ((void)0, 0) -+ -+ if (outlen <= BLAKE2B_OUTBYTES) { -+ TRY(blake2b_init(&blake_state, outlen)); -+ TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); -+ TRY(blake2b_update(&blake_state, in, inlen)); -+ TRY(blake2b_final(&blake_state, out, outlen)); -+ } else { -+ grub_uint32_t toproduce; -+ grub_uint8_t out_buffer[BLAKE2B_OUTBYTES]; -+ grub_uint8_t in_buffer[BLAKE2B_OUTBYTES]; -+ TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES)); -+ TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); -+ TRY(blake2b_update(&blake_state, in, inlen)); -+ TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES)); -+ grub_memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); -+ out += BLAKE2B_OUTBYTES / 2; -+ toproduce = (grub_uint32_t)outlen - BLAKE2B_OUTBYTES / 2; -+ -+ while (toproduce > BLAKE2B_OUTBYTES) { -+ grub_memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); -+ TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer, -+ BLAKE2B_OUTBYTES, NULL, 0)); -+ grub_memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); -+ out += BLAKE2B_OUTBYTES / 2; -+ toproduce -= BLAKE2B_OUTBYTES / 2; -+ } -+ -+ grub_memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); -+ TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL, -+ 0)); -+ grub_memcpy(out, out_buffer, toproduce); -+ } -+fail: -+ clear_internal_memory(&blake_state, sizeof(blake_state)); -+ return ret; -+#undef TRY -+} -+/* Argon2 Team - End Code */ -diff --git a/grub-core/lib/argon2/blake2/blamka-round-ref.h b/grub-core/lib/argon2/blake2/blamka-round-ref.h -new file mode 100644 -index 000000000..7f0071ada ---- /dev/null -+++ b/grub-core/lib/argon2/blake2/blamka-round-ref.h -@@ -0,0 +1,56 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#ifndef BLAKE_ROUND_MKA_H -+#define BLAKE_ROUND_MKA_H -+ -+#include "blake2.h" -+#include "blake2-impl.h" -+ -+/* designed by the Lyra PHC team */ -+static BLAKE2_INLINE grub_uint64_t fBlaMka(grub_uint64_t x, grub_uint64_t y) { -+ const grub_uint64_t m = GRUB_UINT64_C(0xFFFFFFFF); -+ const grub_uint64_t xy = (x & m) * (y & m); -+ return x + y + 2 * xy; -+} -+ -+#define G(a, b, c, d) \ -+ do { \ -+ a = fBlaMka(a, b); \ -+ d = rotr64(d ^ a, 32); \ -+ c = fBlaMka(c, d); \ -+ b = rotr64(b ^ c, 24); \ -+ a = fBlaMka(a, b); \ -+ d = rotr64(d ^ a, 16); \ -+ c = fBlaMka(c, d); \ -+ b = rotr64(b ^ c, 63); \ -+ } while ((void)0, 0) -+ -+#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \ -+ v12, v13, v14, v15) \ -+ do { \ -+ G(v0, v4, v8, v12); \ -+ G(v1, v5, v9, v13); \ -+ G(v2, v6, v10, v14); \ -+ G(v3, v7, v11, v15); \ -+ G(v0, v5, v10, v15); \ -+ G(v1, v6, v11, v12); \ -+ G(v2, v7, v8, v13); \ -+ G(v3, v4, v9, v14); \ -+ } while ((void)0, 0) -+ -+#endif -diff --git a/grub-core/lib/argon2/core.c b/grub-core/lib/argon2/core.c -new file mode 100644 -index 000000000..0fe5b74cb ---- /dev/null -+++ b/grub-core/lib/argon2/core.c -@@ -0,0 +1,506 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+/*For memory wiping*/ -+#ifdef _MSC_VER -+#include <windows.h> -+#include <winbase.h> /* For SecureZeroMemory */ -+#endif -+#if defined __STDC_LIB_EXT1__ -+#define __STDC_WANT_LIB_EXT1__ 1 -+#endif -+#define VC_GE_2005(version) (version >= 1400) -+ -+#include "core.h" -+#include "blake2/blake2.h" -+#include "blake2/blake2-impl.h" -+ -+#ifdef GENKAT -+#include "genkat.h" -+#endif -+ -+#if defined(__clang__) -+#if __has_attribute(optnone) -+#define NOT_OPTIMIZED __attribute__((optnone)) -+#endif -+#elif defined(__GNUC__) -+#define GCC_VERSION \ -+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -+#if GCC_VERSION >= 40400 -+#define NOT_OPTIMIZED __attribute__((optimize("O0"))) -+#endif -+#endif -+#ifndef NOT_OPTIMIZED -+#define NOT_OPTIMIZED -+#endif -+ -+/***************Instance and Position constructors**********/ -+void init_block_value(block *b, grub_uint8_t in) { grub_memset(b->v, in, sizeof(b->v)); } -+ -+void copy_block(block *dst, const block *src) { -+ grub_memcpy(dst->v, src->v, sizeof(grub_uint64_t) * ARGON2_QWORDS_IN_BLOCK); -+} -+ -+void xor_block(block *dst, const block *src) { -+ int i; -+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { -+ dst->v[i] ^= src->v[i]; -+ } -+} -+ -+static void load_block(block *dst, const void *input) { -+ unsigned i; -+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { -+ dst->v[i] = load64((const grub_uint8_t *)input + i * sizeof(dst->v[i])); -+ } -+} -+ -+static void store_block(void *output, const block *src) { -+ unsigned i; -+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { -+ store64((grub_uint8_t *)output + i * sizeof(src->v[i]), src->v[i]); -+ } -+} -+ -+/***************Memory functions*****************/ -+ -+int allocate_memory(const argon2_context *context, grub_uint8_t **memory, -+ grub_size_t num, grub_size_t size) { -+ grub_size_t memory_size = num*size; -+ if (memory == NULL) { -+ return ARGON2_MEMORY_ALLOCATION_ERROR; -+ } -+ -+ /* 1. Check for multiplication overflow */ -+ if (size != 0 && memory_size / size != num) { -+ return ARGON2_MEMORY_ALLOCATION_ERROR; -+ } -+ -+ /* 2. Try to allocate with appropriate allocator */ -+ if (context->allocate_cbk) { -+ (context->allocate_cbk)(memory, memory_size); -+ } else { -+ *memory = grub_malloc(memory_size); -+ } -+ -+ if (*memory == NULL) { -+ return ARGON2_MEMORY_ALLOCATION_ERROR; -+ } -+ -+ return ARGON2_OK; -+} -+ -+void grub_free_memory(const argon2_context *context, grub_uint8_t *memory, -+ grub_size_t num, grub_size_t size) { -+ grub_size_t memory_size = num*size; -+ clear_internal_memory(memory, memory_size); -+ if (context->grub_free_cbk) { -+ (context->grub_free_cbk)(memory, memory_size); -+ } else { -+ grub_free(memory); -+ } -+} -+ -+void NOT_OPTIMIZED secure_wipe_memory(void *v, grub_size_t n) { -+ static void *(*const volatile grub_memset_sec)(void *, int, grub_size_t) = &grub_memset; -+ grub_memset_sec(v, 0, n); -+} -+ -+/* Memory clear flag defaults to true. */ -+int FLAG_clear_internal_memory = 1; -+void clear_internal_memory(void *v, grub_size_t n) { -+ if (FLAG_clear_internal_memory && v) { -+ secure_wipe_memory(v, n); -+ } -+} -+ -+void finalize(const argon2_context *context, argon2_instance_t *instance) { -+ if (context != NULL && instance != NULL) { -+ block blockhash; -+ grub_uint32_t l; -+ -+ copy_block(&blockhash, instance->memory + instance->lane_length - 1); -+ -+ /* XOR the last blocks */ -+ for (l = 1; l < instance->lanes; ++l) { -+ grub_uint32_t last_block_in_lane = -+ l * instance->lane_length + (instance->lane_length - 1); -+ xor_block(&blockhash, instance->memory + last_block_in_lane); -+ } -+ -+ /* Hash the result */ -+ { -+ grub_uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; -+ store_block(blockhash_bytes, &blockhash); -+ blake2b_long(context->out, context->outlen, blockhash_bytes, -+ ARGON2_BLOCK_SIZE); -+ /* clear blockhash and blockhash_bytes */ -+ clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE); -+ clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); -+ } -+ -+#ifdef GENKAT -+ print_tag(context->out, context->outlen); -+#endif -+ -+ grub_free_memory(context, (grub_uint8_t *)instance->memory, -+ instance->memory_blocks, sizeof(block)); -+ } -+} -+ -+grub_uint32_t index_alpha(const argon2_instance_t *instance, -+ const argon2_position_t *position, grub_uint32_t pseudo_rand, -+ int same_lane) { -+ /* -+ * Pass 0: -+ * This lane : all already finished segments plus already constructed -+ * blocks in this segment -+ * Other lanes : all already finished segments -+ * Pass 1+: -+ * This lane : (SYNC_POINTS - 1) last segments plus already constructed -+ * blocks in this segment -+ * Other lanes : (SYNC_POINTS - 1) last segments -+ */ -+ grub_uint32_t reference_area_size; -+ grub_uint64_t relative_position; -+ grub_uint64_t start_position, absolute_position; -+ -+ if (0 == position->pass) { -+ /* First pass */ -+ if (0 == position->slice) { -+ /* First slice */ -+ reference_area_size = -+ position->index - 1; /* all but the previous */ -+ } else { -+ if (same_lane) { -+ /* The same lane => add current segment */ -+ reference_area_size = -+ position->slice * instance->segment_length + -+ position->index - 1; -+ } else { -+ reference_area_size = -+ position->slice * instance->segment_length + -+ ((position->index == 0) ? (-1) : 0); -+ } -+ } -+ } else { -+ /* Second pass */ -+ if (same_lane) { -+ reference_area_size = instance->lane_length - -+ instance->segment_length + position->index - -+ 1; -+ } else { -+ reference_area_size = instance->lane_length - -+ instance->segment_length + -+ ((position->index == 0) ? (-1) : 0); -+ } -+ } -+ -+ /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce -+ * relative position */ -+ relative_position = pseudo_rand; -+ relative_position = relative_position * relative_position >> 32; -+ relative_position = reference_area_size - 1 - -+ (reference_area_size * relative_position >> 32); -+ -+ /* 1.2.5 Computing starting position */ -+ start_position = 0; -+ -+ if (0 != position->pass) { -+ start_position = (position->slice == ARGON2_SYNC_POINTS - 1) -+ ? 0 -+ : (position->slice + 1) * instance->segment_length; -+ } -+ -+ /* 1.2.6. Computing absolute position */ -+ grub_divmod64 (start_position + relative_position, instance->lane_length, -+ &absolute_position); /* absolute position */ -+ return absolute_position; -+} -+ -+/* Single-threaded version for p=1 case */ -+static int fill_memory_blocks_st(argon2_instance_t *instance) { -+ grub_uint32_t r, s, l; -+ -+ for (r = 0; r < instance->passes; ++r) { -+ for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { -+ for (l = 0; l < instance->lanes; ++l) { -+ argon2_position_t position = {r, l, (grub_uint8_t)s, 0}; -+ fill_segment(instance, position); -+ } -+ } -+#ifdef GENKAT -+ internal_kat(instance, r); /* Print all memory blocks */ -+#endif -+ } -+ return ARGON2_OK; -+} -+ -+int fill_memory_blocks(argon2_instance_t *instance) { -+ if (instance == NULL || instance->lanes == 0) { -+ return ARGON2_INCORRECT_PARAMETER; -+ } -+ return fill_memory_blocks_st(instance); -+} -+ -+int validate_inputs(const argon2_context *context) { -+ if (NULL == context) { -+ return ARGON2_INCORRECT_PARAMETER; -+ } -+ -+ if (NULL == context->out) { -+ return ARGON2_OUTPUT_PTR_NULL; -+ } -+ -+ /* Validate output length */ -+ if (ARGON2_MIN_OUTLEN > context->outlen) { -+ return ARGON2_OUTPUT_TOO_SHORT; -+ } -+ -+ if (ARGON2_MAX_OUTLEN < context->outlen) { -+ return ARGON2_OUTPUT_TOO_LONG; -+ } -+ -+ /* Validate password (required param) */ -+ if (NULL == context->pwd) { -+ if (0 != context->pwdlen) { -+ return ARGON2_PWD_PTR_MISMATCH; -+ } -+ } -+ -+ if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) { -+ return ARGON2_PWD_TOO_LONG; -+ } -+ -+ /* Validate salt (required param) */ -+ if (NULL == context->salt) { -+ if (0 != context->saltlen) { -+ return ARGON2_SALT_PTR_MISMATCH; -+ } -+ } -+ -+ if (ARGON2_MIN_SALT_LENGTH > context->saltlen) { -+ return ARGON2_SALT_TOO_SHORT; -+ } -+ -+ if (ARGON2_MAX_SALT_LENGTH < context->saltlen) { -+ return ARGON2_SALT_TOO_LONG; -+ } -+ -+ /* Validate secret (optional param) */ -+ if (NULL == context->secret) { -+ if (0 != context->secretlen) { -+ return ARGON2_SECRET_PTR_MISMATCH; -+ } -+ } else { -+ if (ARGON2_MAX_SECRET < context->secretlen) { -+ return ARGON2_SECRET_TOO_LONG; -+ } -+ } -+ -+ /* Validate associated data (optional param) */ -+ if (NULL == context->ad) { -+ if (0 != context->adlen) { -+ return ARGON2_AD_PTR_MISMATCH; -+ } -+ } else { -+ if (ARGON2_MAX_AD_LENGTH < context->adlen) { -+ return ARGON2_AD_TOO_LONG; -+ } -+ } -+ -+ /* Validate memory cost */ -+ if (ARGON2_MIN_MEMORY > context->m_cost) { -+ return ARGON2_MEMORY_TOO_LITTLE; -+ } -+ -+ if (context->m_cost < 8 * context->lanes) { -+ return ARGON2_MEMORY_TOO_LITTLE; -+ } -+ -+ /* Validate time cost */ -+ if (ARGON2_MIN_TIME > context->t_cost) { -+ return ARGON2_TIME_TOO_SMALL; -+ } -+ -+ if (ARGON2_MAX_TIME < context->t_cost) { -+ return ARGON2_TIME_TOO_LARGE; -+ } -+ -+ /* Validate lanes */ -+ if (ARGON2_MIN_LANES > context->lanes) { -+ return ARGON2_LANES_TOO_FEW; -+ } -+ -+ if (ARGON2_MAX_LANES < context->lanes) { -+ return ARGON2_LANES_TOO_MANY; -+ } -+ -+ /* Validate threads */ -+ if (ARGON2_MIN_THREADS > context->threads) { -+ return ARGON2_THREADS_TOO_FEW; -+ } -+ -+ if (ARGON2_MAX_THREADS < context->threads) { -+ return ARGON2_THREADS_TOO_MANY; -+ } -+ -+ if (NULL != context->allocate_cbk && NULL == context->grub_free_cbk) { -+ return ARGON2_FREE_MEMORY_CBK_NULL; -+ } -+ -+ if (NULL == context->allocate_cbk && NULL != context->grub_free_cbk) { -+ return ARGON2_ALLOCATE_MEMORY_CBK_NULL; -+ } -+ -+ return ARGON2_OK; -+} -+ -+void fill_first_blocks(grub_uint8_t *blockhash, const argon2_instance_t *instance) { -+ grub_uint32_t l; -+ /* Make the first and second block in each lane as G(H0||0||i) or -+ G(H0||1||i) */ -+ grub_uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; -+ for (l = 0; l < instance->lanes; ++l) { -+ -+ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0); -+ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l); -+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, -+ ARGON2_PREHASH_SEED_LENGTH); -+ load_block(&instance->memory[l * instance->lane_length + 0], -+ blockhash_bytes); -+ -+ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1); -+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, -+ ARGON2_PREHASH_SEED_LENGTH); -+ load_block(&instance->memory[l * instance->lane_length + 1], -+ blockhash_bytes); -+ } -+ clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); -+} -+ -+void initial_hash(grub_uint8_t *blockhash, argon2_context *context, -+ argon2_type type) { -+ blake2b_state BlakeHash; -+ grub_uint8_t value[sizeof(grub_uint32_t)]; -+ -+ if (NULL == context || NULL == blockhash) { -+ return; -+ } -+ -+ blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH); -+ -+ store32(&value, context->lanes); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ store32(&value, context->outlen); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ store32(&value, context->m_cost); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ store32(&value, context->t_cost); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ store32(&value, context->version); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ store32(&value, (grub_uint32_t)type); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ store32(&value, context->pwdlen); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ if (context->pwd != NULL) { -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->pwd, -+ context->pwdlen); -+ -+ if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) { -+ secure_wipe_memory(context->pwd, context->pwdlen); -+ context->pwdlen = 0; -+ } -+ } -+ -+ store32(&value, context->saltlen); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ if (context->salt != NULL) { -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->salt, -+ context->saltlen); -+ } -+ -+ store32(&value, context->secretlen); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ if (context->secret != NULL) { -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->secret, -+ context->secretlen); -+ -+ if (context->flags & ARGON2_FLAG_CLEAR_SECRET) { -+ secure_wipe_memory(context->secret, context->secretlen); -+ context->secretlen = 0; -+ } -+ } -+ -+ store32(&value, context->adlen); -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)&value, sizeof(value)); -+ -+ if (context->ad != NULL) { -+ blake2b_update(&BlakeHash, (const grub_uint8_t *)context->ad, -+ context->adlen); -+ } -+ -+ blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH); -+} -+ -+int initialize(argon2_instance_t *instance, argon2_context *context) { -+ grub_uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; -+ int result = ARGON2_OK; -+ -+ if (instance == NULL || context == NULL) -+ return ARGON2_INCORRECT_PARAMETER; -+ instance->context_ptr = context; -+ -+ /* 1. Memory allocation */ -+ result = allocate_memory(context, (grub_uint8_t **)&(instance->memory), -+ instance->memory_blocks, sizeof(block)); -+ if (result != ARGON2_OK) { -+ return result; -+ } -+ -+ /* 2. Initial hashing */ -+ /* H_0 + 8 extra bytes to produce the first blocks */ -+ /* grub_uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */ -+ /* Hashing all inputs */ -+ initial_hash(blockhash, context, instance->type); -+ /* Zeroing 8 extra bytes */ -+ clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, -+ ARGON2_PREHASH_SEED_LENGTH - -+ ARGON2_PREHASH_DIGEST_LENGTH); -+ -+#ifdef GENKAT -+ initial_kat(blockhash, context, instance->type); -+#endif -+ -+ /* 3. Creating first blocks, we always have at least two blocks in a slice -+ */ -+ fill_first_blocks(blockhash, instance); -+ /* Clearing the hash */ -+ clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH); -+ -+ return ARGON2_OK; -+} -diff --git a/grub-core/lib/argon2/core.h b/grub-core/lib/argon2/core.h -new file mode 100644 -index 000000000..bbcd56998 ---- /dev/null -+++ b/grub-core/lib/argon2/core.h -@@ -0,0 +1,228 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#ifndef ARGON2_CORE_H -+#define ARGON2_CORE_H -+ -+#include "argon2.h" -+ -+#define CONST_CAST(x) (x)(grub_addr_t) -+ -+/**********************Argon2 internal constants*******************************/ -+ -+enum argon2_core_constants { -+ /* Memory block size in bytes */ -+ ARGON2_BLOCK_SIZE = 1024, -+ ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, -+ ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16, -+ ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32, -+ ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64, -+ -+ /* Number of pseudo-random values generated by one call to Blake in Argon2i -+ to -+ generate reference block positions */ -+ ARGON2_ADDRESSES_IN_BLOCK = 128, -+ -+ /* Pre-hashing digest length and its extension*/ -+ ARGON2_PREHASH_DIGEST_LENGTH = 64, -+ ARGON2_PREHASH_SEED_LENGTH = 72 -+}; -+ -+/*************************Argon2 internal data types***********************/ -+ -+/* -+ * Structure for the (1KB) memory block implemented as 128 64-bit words. -+ * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no -+ * bounds checking). -+ */ -+typedef struct block_ { grub_uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block; -+ -+/*****************Functions that work with the block******************/ -+ -+/* Initialize each byte of the block with @in */ -+void init_block_value(block *b, grub_uint8_t in); -+ -+/* Copy block @src to block @dst */ -+void copy_block(block *dst, const block *src); -+ -+/* XOR @src onto @dst bytewise */ -+void xor_block(block *dst, const block *src); -+ -+/* -+ * Argon2 instance: memory pointer, number of passes, amount of memory, type, -+ * and derived values. -+ * Used to evaluate the number and location of blocks to construct in each -+ * thread -+ */ -+typedef struct Argon2_instance_t { -+ block *memory; /* Memory pointer */ -+ grub_uint32_t version; -+ grub_uint32_t passes; /* Number of passes */ -+ grub_uint32_t memory_blocks; /* Number of blocks in memory */ -+ grub_uint32_t segment_length; -+ grub_uint32_t lane_length; -+ grub_uint32_t lanes; -+ grub_uint32_t threads; -+ argon2_type type; -+ int print_internals; /* whether to print the memory blocks */ -+ argon2_context *context_ptr; /* points back to original context */ -+} argon2_instance_t; -+ -+/* -+ * Argon2 position: where we construct the block right now. Used to distribute -+ * work between threads. -+ */ -+typedef struct Argon2_position_t { -+ grub_uint32_t pass; -+ grub_uint32_t lane; -+ grub_uint8_t slice; -+ grub_uint32_t index; -+} argon2_position_t; -+ -+/*Struct that holds the inputs for thread handling FillSegment*/ -+typedef struct Argon2_thread_data { -+ argon2_instance_t *instance_ptr; -+ argon2_position_t pos; -+} argon2_thread_data; -+ -+/*************************Argon2 core functions********************************/ -+ -+/* Allocates memory to the given pointer, uses the appropriate allocator as -+ * specified in the context. Total allocated memory is num*size. -+ * @param context argon2_context which specifies the allocator -+ * @param memory pointer to the pointer to the memory -+ * @param size the size in bytes for each element to be allocated -+ * @param num the number of elements to be allocated -+ * @return ARGON2_OK if @memory is a valid pointer and memory is allocated -+ */ -+int allocate_memory(const argon2_context *context, grub_uint8_t **memory, -+ grub_size_t num, grub_size_t size); -+ -+/* -+ * Frees memory at the given pointer, uses the appropriate deallocator as -+ * specified in the context. Also cleans the memory using clear_internal_memory. -+ * @param context argon2_context which specifies the deallocator -+ * @param memory pointer to buffer to be grub_freed -+ * @param size the size in bytes for each element to be deallocated -+ * @param num the number of elements to be deallocated -+ */ -+void grub_free_memory(const argon2_context *context, grub_uint8_t *memory, -+ grub_size_t num, grub_size_t size); -+ -+/* Function that securely cleans the memory. This ignores any flags set -+ * regarding clearing memory. Usually one just calls clear_internal_memory. -+ * @param mem Pointer to the memory -+ * @param s Memory size in bytes -+ */ -+void secure_wipe_memory(void *v, grub_size_t n); -+ -+/* Function that securely clears the memory if FLAG_clear_internal_memory is -+ * set. If the flag isn't set, this function does nothing. -+ * @param mem Pointer to the memory -+ * @param s Memory size in bytes -+ */ -+void clear_internal_memory(void *v, grub_size_t n); -+ -+/* -+ * Computes absolute position of reference block in the lane following a skewed -+ * distribution and using a pseudo-random value as input -+ * @param instance Pointer to the current instance -+ * @param position Pointer to the current position -+ * @param pseudo_rand 32-bit pseudo-random value used to determine the position -+ * @param same_lane Indicates if the block will be taken from the current lane. -+ * If so we can reference the current segment -+ * @pre All pointers must be valid -+ */ -+grub_uint32_t index_alpha(const argon2_instance_t *instance, -+ const argon2_position_t *position, grub_uint32_t pseudo_rand, -+ int same_lane); -+ -+/* -+ * Function that validates all inputs against predefined restrictions and return -+ * an error code -+ * @param context Pointer to current Argon2 context -+ * @return ARGON2_OK if everything is all right, otherwise one of error codes -+ * (all defined in <argon2.h> -+ */ -+int validate_inputs(const argon2_context *context); -+ -+/* -+ * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears -+ * password and secret if needed -+ * @param context Pointer to the Argon2 internal structure containing memory -+ * pointer, and parameters for time and space requirements. -+ * @param blockhash Buffer for pre-hashing digest -+ * @param type Argon2 type -+ * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes -+ * allocated -+ */ -+void initial_hash(grub_uint8_t *blockhash, argon2_context *context, -+ argon2_type type); -+ -+/* -+ * Function creates first 2 blocks per lane -+ * @param instance Pointer to the current instance -+ * @param blockhash Pointer to the pre-hashing digest -+ * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values -+ */ -+void fill_first_blocks(grub_uint8_t *blockhash, const argon2_instance_t *instance); -+ -+/* -+ * Function allocates memory, hashes the inputs with Blake, and creates first -+ * two blocks. Returns the pointer to the main memory with 2 blocks per lane -+ * initialized -+ * @param context Pointer to the Argon2 internal structure containing memory -+ * pointer, and parameters for time and space requirements. -+ * @param instance Current Argon2 instance -+ * @return Zero if successful, -1 if memory failed to allocate. @context->state -+ * will be modified if successful. -+ */ -+int initialize(argon2_instance_t *instance, argon2_context *context); -+ -+/* -+ * XORing the last block of each lane, hashing it, making the tag. Deallocates -+ * the memory. -+ * @param context Pointer to current Argon2 context (use only the out parameters -+ * from it) -+ * @param instance Pointer to current instance of Argon2 -+ * @pre instance->state must point to necessary amount of memory -+ * @pre context->out must point to outlen bytes of memory -+ * @pre if context->grub_free_cbk is not NULL, it should point to a function that -+ * deallocates memory -+ */ -+void finalize(const argon2_context *context, argon2_instance_t *instance); -+ -+/* -+ * Function that fills the segment using previous segments also from other -+ * threads -+ * @param context current context -+ * @param instance Pointer to the current instance -+ * @param position Current position -+ * @pre all block pointers must be valid -+ */ -+void fill_segment(const argon2_instance_t *instance, -+ argon2_position_t position); -+ -+/* -+ * Function that fills the entire memory t_cost times based on the first two -+ * blocks in each lane -+ * @param instance Pointer to the current instance -+ * @return ARGON2_OK if successful, @context->state -+ */ -+int fill_memory_blocks(argon2_instance_t *instance); -+ -+#endif -diff --git a/grub-core/lib/argon2/ref.c b/grub-core/lib/argon2/ref.c -new file mode 100644 -index 000000000..c933df80d ---- /dev/null -+++ b/grub-core/lib/argon2/ref.c -@@ -0,0 +1,190 @@ -+/* -+ * Argon2 reference source code package - reference C implementations -+ * -+ * Copyright 2015 -+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves -+ * -+ * You may use this work under the terms of a Creative Commons CC0 1.0 -+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of -+ * these licenses can be found at: -+ * -+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 -+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * You should have received a copy of both of these licenses along with this -+ * software. If not, they may be obtained at the above URLs. -+ */ -+ -+#include "argon2.h" -+#include "core.h" -+ -+#include "blake2/blamka-round-ref.h" -+#include "blake2/blake2-impl.h" -+#include "blake2/blake2.h" -+ -+ -+/* -+ * Function fills a new memory block and optionally XORs the old block over the new one. -+ * @next_block must be initialized. -+ * @param prev_block Pointer to the previous block -+ * @param ref_block Pointer to the reference block -+ * @param next_block Pointer to the block to be constructed -+ * @param with_xor Whether to XOR into the new block (1) or just overwrite (0) -+ * @pre all block pointers must be valid -+ */ -+static void fill_block(const block *prev_block, const block *ref_block, -+ block *next_block, int with_xor) { -+ block blockR, block_tmp; -+ unsigned i; -+ -+ copy_block(&blockR, ref_block); -+ xor_block(&blockR, prev_block); -+ copy_block(&block_tmp, &blockR); -+ /* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */ -+ if (with_xor) { -+ /* Saving the next block contents for XOR over: */ -+ xor_block(&block_tmp, next_block); -+ /* Now blockR = ref_block + prev_block and -+ block_tmp = ref_block + prev_block + next_block */ -+ } -+ -+ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then -+ (16,17,..31)... finally (112,113,...127) */ -+ for (i = 0; i < 8; ++i) { -+ BLAKE2_ROUND_NOMSG( -+ blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2], -+ blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5], -+ blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8], -+ blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11], -+ blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14], -+ blockR.v[16 * i + 15]); -+ } -+ -+ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then -+ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */ -+ for (i = 0; i < 8; i++) { -+ BLAKE2_ROUND_NOMSG( -+ blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16], -+ blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33], -+ blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64], -+ blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81], -+ blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112], -+ blockR.v[2 * i + 113]); -+ } -+ -+ copy_block(next_block, &block_tmp); -+ xor_block(next_block, &blockR); -+} -+ -+static void next_addresses(block *address_block, block *input_block, -+ const block *zero_block) { -+ input_block->v[6]++; -+ fill_block(zero_block, input_block, address_block, 0); -+ fill_block(zero_block, address_block, address_block, 0); -+} -+ -+void fill_segment(const argon2_instance_t *instance, -+ argon2_position_t position) { -+ block *ref_block = NULL, *curr_block = NULL; -+ block address_block, input_block, zero_block; -+ grub_uint64_t pseudo_rand, ref_index, ref_lane; -+ grub_uint32_t prev_offset, curr_offset; -+ grub_uint32_t starting_index; -+ grub_uint32_t i; -+ int data_independent_addressing; -+ -+ if (instance == NULL) { -+ return; -+ } -+ -+ data_independent_addressing = -+ (instance->type == Argon2_i) || -+ (instance->type == Argon2_id && (position.pass == 0) && -+ (position.slice < ARGON2_SYNC_POINTS / 2)); -+ -+ if (data_independent_addressing) { -+ init_block_value(&zero_block, 0); -+ init_block_value(&input_block, 0); -+ -+ input_block.v[0] = position.pass; -+ input_block.v[1] = position.lane; -+ input_block.v[2] = position.slice; -+ input_block.v[3] = instance->memory_blocks; -+ input_block.v[4] = instance->passes; -+ input_block.v[5] = instance->type; -+ } -+ -+ starting_index = 0; -+ -+ if ((0 == position.pass) && (0 == position.slice)) { -+ starting_index = 2; /* we have already generated the first two blocks */ -+ -+ /* Don't forget to generate the first block of addresses: */ -+ if (data_independent_addressing) { -+ next_addresses(&address_block, &input_block, &zero_block); -+ } -+ } -+ -+ /* Offset of the current block */ -+ curr_offset = position.lane * instance->lane_length + -+ position.slice * instance->segment_length + starting_index; -+ -+ if (0 == curr_offset % instance->lane_length) { -+ /* Last block in this lane */ -+ prev_offset = curr_offset + instance->lane_length - 1; -+ } else { -+ /* Previous block */ -+ prev_offset = curr_offset - 1; -+ } -+ -+ for (i = starting_index; i < instance->segment_length; -+ ++i, ++curr_offset, ++prev_offset) { -+ /*1.1 Rotating prev_offset if needed */ -+ if (curr_offset % instance->lane_length == 1) { -+ prev_offset = curr_offset - 1; -+ } -+ -+ /* 1.2 Computing the index of the reference block */ -+ /* 1.2.1 Taking pseudo-random value from the previous block */ -+ if (data_independent_addressing) { -+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { -+ next_addresses(&address_block, &input_block, &zero_block); -+ } -+ pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; -+ } else { -+ pseudo_rand = instance->memory[prev_offset].v[0]; -+ } -+ -+ /* 1.2.2 Computing the lane of the reference block */ -+ grub_divmod64 (pseudo_rand >> 32, instance->lanes, &ref_lane); -+ -+ if ((position.pass == 0) && (position.slice == 0)) { -+ /* Can not reference other lanes yet */ -+ ref_lane = position.lane; -+ } -+ -+ /* 1.2.3 Computing the number of possible reference block within the -+ * lane. -+ */ -+ position.index = i; -+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF, -+ ref_lane == position.lane); -+ -+ /* 2 Creating a new block */ -+ ref_block = -+ instance->memory + instance->lane_length * ref_lane + ref_index; -+ curr_block = instance->memory + curr_offset; -+ if (ARGON2_VERSION_10 == instance->version) { -+ /* version 1.2.1 and earlier: overwrite, not XOR */ -+ fill_block(instance->memory + prev_offset, ref_block, curr_block, 0); -+ } else { -+ if(0 == position.pass) { -+ fill_block(instance->memory + prev_offset, ref_block, -+ curr_block, 0); -+ } else { -+ fill_block(instance->memory + prev_offset, ref_block, -+ curr_block, 1); -+ } -+ } -+ } -+} --- -2.39.5 - diff --git a/config/grub/xhci/patches/0006-Error-on-missing-Argon2id-parameters.patch b/config/grub/xhci/patches/0006-Error-on-missing-Argon2id-parameters.patch deleted file mode 100644 index 3fc6d3dc..00000000 --- a/config/grub/xhci/patches/0006-Error-on-missing-Argon2id-parameters.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c75424efa3a6357d4785c7a66721809a642b3968 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 06/26] Error on missing Argon2id parameters - -Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> ---- - grub-core/disk/luks2.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c -index b17cd2115..bbd8f5579 100644 ---- a/grub-core/disk/luks2.c -+++ b/grub-core/disk/luks2.c -@@ -39,6 +39,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); - enum grub_luks2_kdf_type - { - LUKS2_KDF_TYPE_ARGON2I, -+ LUKS2_KDF_TYPE_ARGON2ID, - LUKS2_KDF_TYPE_PBKDF2 - }; - typedef enum grub_luks2_kdf_type grub_luks2_kdf_type_t; -@@ -91,7 +92,7 @@ struct grub_luks2_keyslot - grub_int64_t time; - grub_int64_t memory; - grub_int64_t cpus; -- } argon2i; -+ } argon2; - struct - { - const char *hash; -@@ -161,10 +162,11 @@ luks2_parse_keyslot (grub_luks2_keyslot_t *out, const grub_json_t *keyslot) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing or invalid KDF"); - else if (!grub_strcmp (type, "argon2i") || !grub_strcmp (type, "argon2id")) - { -- out->kdf.type = LUKS2_KDF_TYPE_ARGON2I; -- if (grub_json_getint64 (&out->kdf.u.argon2i.time, &kdf, "time") || -- grub_json_getint64 (&out->kdf.u.argon2i.memory, &kdf, "memory") || -- grub_json_getint64 (&out->kdf.u.argon2i.cpus, &kdf, "cpus")) -+ out->kdf.type = !grub_strcmp (type, "argon2i") -+ ? LUKS2_KDF_TYPE_ARGON2I : LUKS2_KDF_TYPE_ARGON2ID; -+ if (grub_json_getint64 (&out->kdf.u.argon2.time, &kdf, "time") || -+ grub_json_getint64 (&out->kdf.u.argon2.memory, &kdf, "memory") || -+ grub_json_getint64 (&out->kdf.u.argon2.cpus, &kdf, "cpus")) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing Argon2i parameters"); - } - else if (!grub_strcmp (type, "pbkdf2")) -@@ -460,6 +462,7 @@ luks2_decrypt_key (grub_uint8_t *out_key, - switch (k->kdf.type) - { - case LUKS2_KDF_TYPE_ARGON2I: -+ case LUKS2_KDF_TYPE_ARGON2ID: - ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Argon2 not supported"); - goto err; - case LUKS2_KDF_TYPE_PBKDF2: --- -2.39.5 - diff --git a/config/grub/xhci/patches/0007-Compile-with-Argon2id-support.patch b/config/grub/xhci/patches/0007-Compile-with-Argon2id-support.patch deleted file mode 100644 index 0f9d92ee..00000000 --- a/config/grub/xhci/patches/0007-Compile-with-Argon2id-support.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 801aa8b85d8f3b999f4660cc299a3517e811f0bb Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 07/26] Compile with Argon2id support - -Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> ---- - Makefile.util.def | 6 +++++- - grub-core/Makefile.core.def | 2 +- - grub-core/disk/luks2.c | 13 +++++++++++-- - 3 files changed, 17 insertions(+), 4 deletions(-) - -diff --git a/Makefile.util.def b/Makefile.util.def -index 038253b37..2f19569c9 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -3,7 +3,7 @@ AutoGen definitions Makefile.tpl; - library = { - name = libgrubkern.a; - cflags = '$(CFLAGS_GNULIB)'; -- cppflags = '$(CPPFLAGS_GNULIB) -I$(srcdir)/grub-core/lib/json'; -+ cppflags = '$(CPPFLAGS_GNULIB) -I$(srcdir)/grub-core/lib/json -I$(srcdir)/grub-core/lib/argon2'; - - common = util/misc.c; - common = grub-core/kern/command.c; -@@ -36,6 +36,10 @@ library = { - common = grub-core/kern/misc.c; - common = grub-core/kern/partition.c; - common = grub-core/lib/crypto.c; -+ common = grub-core/lib/argon2/argon2.c; -+ common = grub-core/lib/argon2/core.c; -+ common = grub-core/lib/argon2/ref.c; -+ common = grub-core/lib/argon2/blake2/blake2b.c; - common = grub-core/lib/json/json.c; - common = grub-core/disk/luks.c; - common = grub-core/disk/luks2.c; -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 0ee65d54d..cd29a9df8 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1242,7 +1242,7 @@ module = { - common = disk/luks2.c; - common = lib/gnulib/base64.c; - cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; -- cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/json'; -+ cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/json -I$(srcdir)/lib/argon2'; - }; - - module = { -diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c -index bbd8f5579..02cd615d9 100644 ---- a/grub-core/disk/luks2.c -+++ b/grub-core/disk/luks2.c -@@ -28,6 +28,7 @@ - #include <grub/i18n.h> - #include <grub/safemath.h> - -+#include <argon2.h> - #include <base64.h> - #include <json.h> - -@@ -463,8 +464,16 @@ luks2_decrypt_key (grub_uint8_t *out_key, - { - case LUKS2_KDF_TYPE_ARGON2I: - case LUKS2_KDF_TYPE_ARGON2ID: -- ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Argon2 not supported"); -- goto err; -+ ret = argon2_hash (k->kdf.u.argon2.time, k->kdf.u.argon2.memory, k->kdf.u.argon2.cpus, -+ passphrase, passphraselen, salt, saltlen, area_key, k->area.key_size, -+ k->kdf.type == LUKS2_KDF_TYPE_ARGON2I ? Argon2_i : Argon2_id, -+ ARGON2_VERSION_NUMBER); -+ if (ret) -+ { -+ grub_dprintf ("luks2", "Argon2 failed: %s\n", argon2_error_message (ret)); -+ goto err; -+ } -+ break; - case LUKS2_KDF_TYPE_PBKDF2: - hash = grub_crypto_lookup_md_by_name (k->kdf.u.pbkdf2.hash); - if (!hash) --- -2.39.5 - diff --git a/config/grub/xhci/patches/0008-Make-grub-install-work-with-Argon2.patch b/config/grub/xhci/patches/0008-Make-grub-install-work-with-Argon2.patch deleted file mode 100644 index 21ad8855..00000000 --- a/config/grub/xhci/patches/0008-Make-grub-install-work-with-Argon2.patch +++ /dev/null @@ -1,26 +0,0 @@ -From c114684bb103af427296e40b78adc0d036a9b237 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 08/26] Make grub-install work with Argon2 - -Signed-off-by: Nicholas Johnson <nick@nicholasjohnson.ch> ---- - util/grub-install.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/util/grub-install.c b/util/grub-install.c -index 060246589..059036d3c 100644 ---- a/util/grub-install.c -+++ b/util/grub-install.c -@@ -448,6 +448,8 @@ probe_mods (grub_disk_t disk) - { - grub_util_cryptodisk_get_abstraction (disk, - push_cryptodisk_module, NULL); -+ /* HACK: always push argon2 */ -+ grub_install_push_module ("argon2"); - have_abstractions = 1; - have_cryptodisk = 1; - } --- -2.39.5 - diff --git a/config/grub/xhci/patches/0009-at_keyboard-coreboot-force-scancodes2-translate.patch b/config/grub/xhci/patches/0009-at_keyboard-coreboot-force-scancodes2-translate.patch deleted file mode 100644 index 87164461..00000000 --- a/config/grub/xhci/patches/0009-at_keyboard-coreboot-force-scancodes2-translate.patch +++ /dev/null @@ -1,107 +0,0 @@ -From dfbfe525d6f138e3db1e683096302045c064096f Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Mon, 30 Oct 2023 22:19:21 +0000 -Subject: [PATCH 09/26] at_keyboard coreboot: force scancodes2+translate - -Scan code set 2 with translation should be assumed in -every case, as the default starting position. - -However, GRUB is trying to detect and use other modes -such as set 2 without translation, or set 1 without -translation from set 2; it also detects no-mode and -assumes mode 1, on really old keyboards. - -The current behaviour has been retained, for everything -except GRUB_MACHINE_COREBOOT; for the latter, scan code -set 2 with translation is hardcoded, and forced in code. - -This is required to make keyboard initialisation work on -the MEC5035 EC used by the Dell Latitude E6400, when -running GRUB as a coreboot payload on that laptop. The -EC reports scancode set 2 with translation when probed, -but actually only outputs scancode set 1. - -Since GRUB is attempting to use it without translation, -and since the machine reports set 2 with translation, -but only ever outputs set 1 scancodes, this results in -wrong keypresses for every key. - -This fix fixed that, by forcing set 2 with translation, -treating it as set 1, but only on coreboot. This is the -same behaviour used in GNU+Linux systems and SeaBIOS. -With this change, GRUB keyboard initialisation now works -just fine on those machines. - -This has *also* been tested on other coreboot machines -running GRUB; several HP EliteBooks, ThinkPads and -Dell Precision T1650. All seems to work just fine. - -Signed-off-by: Leah Rowe <leah@libreboot.org> ---- - grub-core/term/at_keyboard.c | 20 ++++++++++++++++++-- - 1 file changed, 18 insertions(+), 2 deletions(-) - -diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c -index f8a129eb7..8207225c2 100644 ---- a/grub-core/term/at_keyboard.c -+++ b/grub-core/term/at_keyboard.c -@@ -138,6 +138,7 @@ write_mode (int mode) - return (i != GRUB_AT_TRIES); - } - -+#if !defined (GRUB_MACHINE_COREBOOT) - static int - query_mode (void) - { -@@ -161,10 +162,12 @@ query_mode (void) - return 3; - return 0; - } -+#endif - - static void - set_scancodes (void) - { -+#if !defined (GRUB_MACHINE_COREBOOT) - /* You must have visited computer museum. Keyboard without scancode set - knowledge. Assume XT. */ - if (!grub_keyboard_orig_set) -@@ -173,20 +176,33 @@ set_scancodes (void) - ps2_state.current_set = 1; - return; - } -+#endif - - #if !USE_SCANCODE_SET - ps2_state.current_set = 1; - return; --#else -+#endif - -+#if defined (GRUB_MACHINE_COREBOOT) -+ /* enable translation */ -+ grub_keyboard_controller_write (grub_keyboard_controller_orig -+ & ~KEYBOARD_AT_DISABLE); -+#else -+ /* if not coreboot, disable translation and try mode 2 first, before 1 */ - grub_keyboard_controller_write (grub_keyboard_controller_orig - & ~KEYBOARD_AT_TRANSLATE - & ~KEYBOARD_AT_DISABLE); -+#endif - - keyboard_controller_wait_until_ready (); - grub_outb (KEYBOARD_COMMAND_ENABLE, KEYBOARD_REG_DATA); -- - write_mode (2); -+ -+#if defined (GRUB_MACHINE_COREBOOT) -+ /* mode 2 with translation, so make grub treat as set 1 */ -+ ps2_state.current_set = 1; -+#else -+ /* if not coreboot, translation isn't set; test 2 and fall back to 1 */ - ps2_state.current_set = query_mode (); - grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set); - if (ps2_state.current_set == 2) --- -2.39.5 - diff --git a/config/grub/xhci/patches/0010-keylayouts-don-t-print-Unknown-key-message.patch b/config/grub/xhci/patches/0010-keylayouts-don-t-print-Unknown-key-message.patch deleted file mode 100644 index 607f3541..00000000 --- a/config/grub/xhci/patches/0010-keylayouts-don-t-print-Unknown-key-message.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 18f88785a46e6657e1404e1914638f4768d65008 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Tue, 31 Oct 2023 10:33:28 +0000 -Subject: [PATCH 10/26] keylayouts: don't print "Unknown key" message - -on keyboards with stuck keys, this results in GRUB just -spewing it repeatedly, preventing use of GRUB. - -in such cases, it's still possible to use the keyboard, -and we should let the user at least boot. - -it often appears when people plug in faulty usb keyboards, -but can appear for laptop keyboards too; one of my e6400 -has stuck keys. - -with this patch, grub should be a bit more reliable in -terms of user experience, when the keyboard is faulty. - -Signed-off-by: Leah Rowe <leah@libreboot.org> ---- - grub-core/commands/keylayouts.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c -index aa3ba34f2..445fa0601 100644 ---- a/grub-core/commands/keylayouts.c -+++ b/grub-core/commands/keylayouts.c -@@ -174,7 +174,6 @@ grub_term_map_key (grub_keyboard_key_t code, int status) - key = map_key_core (code, status, &alt_gr_consumed); - - if (key == 0 || key == GRUB_TERM_SHIFT) { -- grub_printf ("Unknown key 0x%x detected\n", code); - return GRUB_TERM_NO_KEY; - } - --- -2.39.5 - diff --git a/config/grub/xhci/patches/0011-don-t-print-missing-prefix-errors-on-the-screen.patch b/config/grub/xhci/patches/0011-don-t-print-missing-prefix-errors-on-the-screen.patch deleted file mode 100644 index 4f03515e..00000000 --- a/config/grub/xhci/patches/0011-don-t-print-missing-prefix-errors-on-the-screen.patch +++ /dev/null @@ -1,102 +0,0 @@ -From afd68d1e132970e4fa8e26e9ca0ccb7efb69dc37 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 5 Nov 2023 16:14:58 +0000 -Subject: [PATCH 11/26] don't print missing prefix errors on the screen - -we do actually set the prefix. this patch modifies -grub to still set grub_errno and return accordingly, -so the behaviour is otherwise identical, but it will -no longer print a warning message on the screen. - -Signed-off-by: Leah Rowe <leah@libreboot.org> ---- - grub-core/commands/keylayouts.c | 2 +- - grub-core/commands/loadenv.c | 2 +- - grub-core/commands/nativedisk.c | 2 +- - grub-core/efiemu/main.c | 3 +-- - grub-core/font/font.c | 2 +- - grub-core/kern/dl.c | 2 +- - 6 files changed, 6 insertions(+), 7 deletions(-) - -diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c -index 445fa0601..00bcf7025 100644 ---- a/grub-core/commands/keylayouts.c -+++ b/grub-core/commands/keylayouts.c -@@ -211,7 +211,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), - { - const char *prefix = grub_env_get ("prefix"); - if (!prefix) -- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable `%s' isn't set"), "prefix"); -+ return (grub_errno = GRUB_ERR_BAD_ARGUMENT); - filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]); - if (!filename) - return grub_errno; -diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c -index 166445849..699b39bfa 100644 ---- a/grub-core/commands/loadenv.c -+++ b/grub-core/commands/loadenv.c -@@ -58,7 +58,7 @@ open_envblk_file (char *filename, - prefix = grub_env_get ("prefix"); - if (! prefix) - { -- grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); -+ grub_errno = GRUB_ERR_FILE_NOT_FOUND; - return 0; - } - -diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c -index 580c8d3b0..6806bff9c 100644 ---- a/grub-core/commands/nativedisk.c -+++ b/grub-core/commands/nativedisk.c -@@ -186,7 +186,7 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)), - prefix = grub_env_get ("prefix"); - - if (! prefix) -- return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); -+ return (grub_errno = GRUB_ERR_FILE_NOT_FOUND); - - if (prefix) - path_prefix = (prefix[0] == '(') ? grub_strchr (prefix, ')') : NULL; -diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c -index e7037f4ed..e5d4dbff1 100644 ---- a/grub-core/efiemu/main.c -+++ b/grub-core/efiemu/main.c -@@ -231,8 +231,7 @@ grub_efiemu_autocore (void) - prefix = grub_env_get ("prefix"); - - if (! prefix) -- return grub_error (GRUB_ERR_FILE_NOT_FOUND, -- N_("variable `%s' isn't set"), "prefix"); -+ return (grub_errno = GRUB_ERR_FILE_NOT_FOUND); - - suffix = grub_efiemu_get_default_core_name (); - -diff --git a/grub-core/font/font.c b/grub-core/font/font.c -index 18de52562..2a0fea6c8 100644 ---- a/grub-core/font/font.c -+++ b/grub-core/font/font.c -@@ -461,7 +461,7 @@ grub_font_load (const char *filename) - - if (!prefix) - { -- grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); -+ grub_errno = GRUB_ERR_FILE_NOT_FOUND; - goto fail; - } - file = try_open_from_prefix (prefix, filename); -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 4a3be8568..6ae3d73f8 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -881,7 +881,7 @@ grub_dl_load (const char *name) - return 0; - - if (! grub_dl_dir) { -- grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); -+ grub_errno = GRUB_ERR_FILE_NOT_FOUND; - return 0; - } - --- -2.39.5 - diff --git a/config/grub/xhci/patches/0012-don-t-print-error-if-module-not-found.patch b/config/grub/xhci/patches/0012-don-t-print-error-if-module-not-found.patch deleted file mode 100644 index e817ca85..00000000 --- a/config/grub/xhci/patches/0012-don-t-print-error-if-module-not-found.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 06f9480a670d374e1599bf9871f6cd26656418a7 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 5 Nov 2023 16:36:22 +0000 -Subject: [PATCH 12/26] don't print error if module not found - -still set grub_errno accordingly, and otherwise -behave the same. in libreboot, we remove a lot of -modules but then rely on loading a grub.cfg -provided by a distro; in almost all cases that works, -but also in almost all cases, that will try to load -a module we don't actually need, but then it prints -a message. this can annoy some users, so silence it. - -Signed-off-by: Leah Rowe <leah@libreboot.org> ---- - grub-core/kern/dl.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c -index 6ae3d73f8..4c15027fe 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -511,7 +511,7 @@ grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e) - - s = grub_dl_find_section (e, ".modname"); - if (!s) -- return grub_error (GRUB_ERR_BAD_MODULE, "no module name found"); -+ return (grub_errno = GRUB_ERR_BAD_MODULE); - - mod->name = grub_strdup ((char *) e + s->sh_offset); - if (! mod->name) --- -2.39.5 - diff --git a/config/grub/xhci/patches/0013-don-t-print-empty-error-messages.patch b/config/grub/xhci/patches/0013-don-t-print-empty-error-messages.patch deleted file mode 100644 index 4bf96b50..00000000 --- a/config/grub/xhci/patches/0013-don-t-print-empty-error-messages.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 272c5f5724c0790aff48b0d6ba75928de2275b33 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 5 Nov 2023 17:25:20 +0000 -Subject: [PATCH 13/26] don't print empty error messages - -this is part two of the quest to kill the prefix -error message. after i disabled prefix-related -messages, it still printed "error: ." on screen. - -Signed-off-by: Leah Rowe <leah@libreboot.org> ---- - grub-core/kern/err.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c -index 53c734de7..7cac53983 100644 ---- a/grub-core/kern/err.c -+++ b/grub-core/kern/err.c -@@ -107,7 +107,8 @@ grub_print_error (void) - { - if (grub_errno != GRUB_ERR_NONE) - { -- grub_err_printf (_("error: %s.\n"), grub_errmsg); -+ if (grub_strlen(grub_errmsg) > 0) -+ grub_err_printf (_("error: %s.\n"), grub_errmsg); - grub_err_printed_errors++; - } - } --- -2.39.5 - diff --git a/config/grub/xhci/patches/0014-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch b/config/grub/xhci/patches/0014-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch deleted file mode 100644 index c04e138e..00000000 --- a/config/grub/xhci/patches/0014-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch +++ /dev/null @@ -1,246 +0,0 @@ -From 1c5716f42deb27b1111839b9782fd06b077eaa90 Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Sun, 15 Nov 2020 19:00:27 +0100 -Subject: [PATCH 14/26] grub-core/bus/usb: Parse SuperSpeed companion - descriptors - -Parse the SS_ENDPOINT_COMPANION descriptor, which is only present on USB 3.0 -capable devices and xHCI controllers. Make the descendp an array of pointers -to the endpoint descriptor as it's no longer an continous array. - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> ---- - grub-core/bus/usb/serial/common.c | 2 +- - grub-core/bus/usb/usb.c | 44 +++++++++++++++++++------------ - grub-core/bus/usb/usbhub.c | 22 ++++++++++++---- - grub-core/commands/usbtest.c | 2 +- - grub-core/disk/usbms.c | 2 +- - grub-core/term/usb_keyboard.c | 2 +- - include/grub/usb.h | 2 +- - include/grub/usbdesc.h | 11 +++++++- - 8 files changed, 59 insertions(+), 28 deletions(-) - -diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c -index e9c995a0a..fc847d66d 100644 ---- a/grub-core/bus/usb/serial/common.c -+++ b/grub-core/bus/usb/serial/common.c -@@ -72,7 +72,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, - for (j = 0; j < interf->endpointcnt; j++) - { - struct grub_usb_desc_endp *endp; -- endp = &usbdev->config[0].interf[interfno].descendp[j]; -+ endp = usbdev->config[0].interf[interfno].descendp[j]; - - if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2 - && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING -diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c -index 7bd49d201..e578af793 100644 ---- a/grub-core/bus/usb/usb.c -+++ b/grub-core/bus/usb/usb.c -@@ -118,7 +118,7 @@ grub_usb_device_initialize (grub_usb_device_t dev) - struct grub_usb_desc_device *descdev; - struct grub_usb_desc_config config; - grub_usb_err_t err; -- int i; -+ int i, j; - - /* First we have to read first 8 bytes only and determine - * max. size of packet */ -@@ -152,6 +152,7 @@ grub_usb_device_initialize (grub_usb_device_t dev) - int currif; - char *data; - struct grub_usb_desc *desc; -+ struct grub_usb_desc_endp *endp; - - /* First just read the first 4 bytes of the configuration - descriptor, after that it is known how many bytes really have -@@ -201,24 +202,27 @@ grub_usb_device_initialize (grub_usb_device_t dev) - = (struct grub_usb_desc_if *) &data[pos]; - pos += dev->config[i].interf[currif].descif->length; - -+ dev->config[i].interf[currif].descendp = grub_malloc ( -+ dev->config[i].interf[currif].descif->endpointcnt * -+ sizeof(struct grub_usb_desc_endp)); -+ -+ j = 0; - while (pos < config.totallen) - { - desc = (struct grub_usb_desc *)&data[pos]; -- if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT) -- break; -- if (!desc->length) -- { -- err = GRUB_USB_ERR_BADDEVICE; -- goto fail; -- } -- pos += desc->length; -- } -- -- /* Point to the first endpoint. */ -- dev->config[i].interf[currif].descendp -- = (struct grub_usb_desc_endp *) &data[pos]; -- pos += (sizeof (struct grub_usb_desc_endp) -- * dev->config[i].interf[currif].descif->endpointcnt); -+ if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT) { -+ endp = (struct grub_usb_desc_endp *) &data[pos]; -+ dev->config[i].interf[currif].descendp[j++] = endp; -+ pos += desc->length; -+ } else { -+ if (!desc->length) -+ { -+ err = GRUB_USB_ERR_BADDEVICE; -+ goto fail; -+ } -+ pos += desc->length; -+ } -+ } - } - } - -@@ -226,8 +230,14 @@ grub_usb_device_initialize (grub_usb_device_t dev) - - fail: - -- for (i = 0; i < GRUB_USB_MAX_CONF; i++) -+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) { -+ int currif; -+ -+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++) -+ grub_free (dev->config[i].interf[currif].descendp); -+ - grub_free (dev->config[i].descconf); -+ } - - return err; - } -diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c -index f5608e330..2ae29cba1 100644 ---- a/grub-core/bus/usb/usbhub.c -+++ b/grub-core/bus/usb/usbhub.c -@@ -82,8 +82,14 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, - if (i == GRUB_USBHUB_MAX_DEVICES) - { - grub_error (GRUB_ERR_IO, "can't assign address to USB device"); -- for (i = 0; i < GRUB_USB_MAX_CONF; i++) -- grub_free (dev->config[i].descconf); -+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) { -+ int currif; -+ -+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++) -+ grub_free (dev->config[i].interf[currif].descendp); -+ -+ grub_free (dev->config[i].descconf); -+ } - grub_free (dev); - return NULL; - } -@@ -96,8 +102,14 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, - i, 0, 0, NULL); - if (err) - { -- for (i = 0; i < GRUB_USB_MAX_CONF; i++) -- grub_free (dev->config[i].descconf); -+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) { -+ int currif; -+ -+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++) -+ grub_free (dev->config[i].interf[currif].descendp); -+ -+ grub_free (dev->config[i].descconf); -+ } - grub_free (dev); - return NULL; - } -@@ -176,7 +188,7 @@ grub_usb_add_hub (grub_usb_device_t dev) - i++) - { - struct grub_usb_desc_endp *endp = NULL; -- endp = &dev->config[0].interf[0].descendp[i]; -+ endp = dev->config[0].interf[0].descendp[i]; - - if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp) - == GRUB_USB_EP_INTERRUPT) -diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c -index 2c6d93fe6..55a657635 100644 ---- a/grub-core/commands/usbtest.c -+++ b/grub-core/commands/usbtest.c -@@ -185,7 +185,7 @@ usb_iterate (grub_usb_device_t dev, void *data __attribute__ ((unused))) - for (j = 0; j < interf->endpointcnt; j++) - { - struct grub_usb_desc_endp *endp; -- endp = &dev->config[0].interf[i].descendp[j]; -+ endp = dev->config[0].interf[i].descendp[j]; - - grub_printf ("Endpoint #%d: %s, max packed size: %d, transfer type: %s, latency: %d\n", - endp->endp_addr & 15, -diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c -index b81e3ad9d..b1512dc12 100644 ---- a/grub-core/disk/usbms.c -+++ b/grub-core/disk/usbms.c -@@ -184,7 +184,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) - for (j = 0; j < interf->endpointcnt; j++) - { - struct grub_usb_desc_endp *endp; -- endp = &usbdev->config[0].interf[interfno].descendp[j]; -+ endp = usbdev->config[0].interf[interfno].descendp[j]; - - if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2) - /* Bulk IN endpoint. */ -diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c -index 7322d8dff..d590979f5 100644 ---- a/grub-core/term/usb_keyboard.c -+++ b/grub-core/term/usb_keyboard.c -@@ -175,7 +175,7 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) - for (j = 0; j < usbdev->config[configno].interf[interfno].descif->endpointcnt; - j++) - { -- endp = &usbdev->config[configno].interf[interfno].descendp[j]; -+ endp = usbdev->config[configno].interf[interfno].descendp[j]; - - if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp) - == GRUB_USB_EP_INTERRUPT) -diff --git a/include/grub/usb.h b/include/grub/usb.h -index 0f346af12..688c11f6d 100644 ---- a/include/grub/usb.h -+++ b/include/grub/usb.h -@@ -153,7 +153,7 @@ struct grub_usb_interface - { - struct grub_usb_desc_if *descif; - -- struct grub_usb_desc_endp *descendp; -+ struct grub_usb_desc_endp **descendp; - - /* A driver is handling this interface. Do we need to support multiple drivers - for single interface? -diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h -index aac5ab05a..bb2ab2e27 100644 ---- a/include/grub/usbdesc.h -+++ b/include/grub/usbdesc.h -@@ -29,7 +29,8 @@ typedef enum { - GRUB_USB_DESCRIPTOR_INTERFACE, - GRUB_USB_DESCRIPTOR_ENDPOINT, - GRUB_USB_DESCRIPTOR_DEBUG = 10, -- GRUB_USB_DESCRIPTOR_HUB = 0x29 -+ GRUB_USB_DESCRIPTOR_HUB = 0x29, -+ GRUB_USB_DESCRIPTOR_SS_ENDPOINT_COMPANION = 0x30 - } grub_usb_descriptor_t; - - struct grub_usb_desc -@@ -105,6 +106,14 @@ struct grub_usb_desc_endp - grub_uint8_t interval; - } GRUB_PACKED; - -+struct grub_usb_desc_ssep { -+ grub_uint8_t length; -+ grub_uint8_t type; -+ grub_uint8_t maxburst; -+ grub_uint8_t attrib; -+ grub_uint16_t interval; -+} GRUB_PACKED; -+ - struct grub_usb_desc_str - { - grub_uint8_t length; --- -2.39.5 - diff --git a/config/grub/xhci/patches/0015-usb-Add-enum-for-xHCI.patch b/config/grub/xhci/patches/0015-usb-Add-enum-for-xHCI.patch deleted file mode 100644 index 4de9d894..00000000 --- a/config/grub/xhci/patches/0015-usb-Add-enum-for-xHCI.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 260f27e1ea1dbcdeb63d4411dbdddb97ebb39668 Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Mon, 7 Dec 2020 08:41:22 +0100 -Subject: [PATCH 15/26] usb: Add enum for xHCI - -Will be used in future patches. - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> ---- - include/grub/usb.h | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/include/grub/usb.h b/include/grub/usb.h -index 688c11f6d..ea6ee8c2c 100644 ---- a/include/grub/usb.h -+++ b/include/grub/usb.h -@@ -51,7 +51,8 @@ typedef enum - GRUB_USB_SPEED_NONE, - GRUB_USB_SPEED_LOW, - GRUB_USB_SPEED_FULL, -- GRUB_USB_SPEED_HIGH -+ GRUB_USB_SPEED_HIGH, -+ GRUB_USB_SPEED_SUPER - } grub_usb_speed_t; - - typedef int (*grub_usb_iterate_hook_t) (grub_usb_device_t dev, void *data); --- -2.39.5 - diff --git a/config/grub/xhci/patches/0016-usbtrans-Set-default-maximum-packet-size.patch b/config/grub/xhci/patches/0016-usbtrans-Set-default-maximum-packet-size.patch deleted file mode 100644 index 908c3adb..00000000 --- a/config/grub/xhci/patches/0016-usbtrans-Set-default-maximum-packet-size.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 97f71a34c011ad9d37b96c02eb7483fe253c6025 Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Mon, 7 Dec 2020 08:41:23 +0100 -Subject: [PATCH 16/26] usbtrans: Set default maximum packet size - -Set the maximum packet size to 512 for SuperSpeed devices. - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> ---- - grub-core/bus/usb/usbtrans.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c -index c5680b33a..c1080bb33 100644 ---- a/grub-core/bus/usb/usbtrans.c -+++ b/grub-core/bus/usb/usbtrans.c -@@ -128,8 +128,12 @@ grub_usb_control_msg (grub_usb_device_t dev, - setupdata_addr = grub_dma_get_phys (setupdata_chunk); - - /* Determine the maximum packet size. */ -- if (dev->descdev.maxsize0) -+ if (dev->descdev.maxsize0 && dev->speed != GRUB_USB_SPEED_SUPER) - max = dev->descdev.maxsize0; -+ else if (dev->descdev.maxsize0 && dev->speed == GRUB_USB_SPEED_SUPER) -+ max = 1UL << dev->descdev.maxsize0; -+ else if (dev->speed == GRUB_USB_SPEED_SUPER) -+ max = 512; - else - max = 64; - --- -2.39.5 - diff --git a/config/grub/xhci/patches/0017-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch b/config/grub/xhci/patches/0017-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch deleted file mode 100644 index e4798a8d..00000000 --- a/config/grub/xhci/patches/0017-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch +++ /dev/null @@ -1,121 +0,0 @@ -From ea5081844c3112b582f52360cfb14ef95b56f5e1 Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Sun, 15 Nov 2020 19:51:42 +0100 -Subject: [PATCH 17/26] grub-core/bus/usb: Add function pointer for - attach/detach events - -The xHCI code needs to be called for attaching or detaching a device. -Introduce two functions pointers and call it from the USB hub code. - -Will be used in future commits, currently this doesn't change any functionality. - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> ---- - grub-core/bus/usb/ehci.c | 2 ++ - grub-core/bus/usb/ohci.c | 2 ++ - grub-core/bus/usb/uhci.c | 2 ++ - grub-core/bus/usb/usbhub.c | 19 +++++++++++++++++++ - include/grub/usb.h | 4 ++++ - 5 files changed, 29 insertions(+) - -diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c -index 2db07c7c0..1ee056015 100644 ---- a/grub-core/bus/usb/ehci.c -+++ b/grub-core/bus/usb/ehci.c -@@ -1812,6 +1812,8 @@ static struct grub_usb_controller_dev usb_controller = { - .hubports = grub_ehci_hubports, - .portstatus = grub_ehci_portstatus, - .detect_dev = grub_ehci_detect_dev, -+ .attach_dev = NULL, -+ .detach_dev = NULL, - /* estimated max. count of TDs for one bulk transfer */ - .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4 - }; -diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c -index 5363a61f6..7a3f3e154 100644 ---- a/grub-core/bus/usb/ohci.c -+++ b/grub-core/bus/usb/ohci.c -@@ -1440,6 +1440,8 @@ static struct grub_usb_controller_dev usb_controller = - .hubports = grub_ohci_hubports, - .portstatus = grub_ohci_portstatus, - .detect_dev = grub_ohci_detect_dev, -+ .attach_dev = NULL, -+ .detach_dev = NULL, - /* estimated max. count of TDs for one bulk transfer */ - .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4 - }; -diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c -index 0fdea4c1e..03c4605b2 100644 ---- a/grub-core/bus/usb/uhci.c -+++ b/grub-core/bus/usb/uhci.c -@@ -845,6 +845,8 @@ static struct grub_usb_controller_dev usb_controller = - .hubports = grub_uhci_hubports, - .portstatus = grub_uhci_portstatus, - .detect_dev = grub_uhci_detect_dev, -+ .attach_dev = NULL, -+ .detach_dev = NULL, - /* estimated max. count of TDs for one bulk transfer */ - .max_bulk_tds = N_TD * 3 / 4 - }; -diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c -index 2ae29cba1..8e963e84b 100644 ---- a/grub-core/bus/usb/usbhub.c -+++ b/grub-core/bus/usb/usbhub.c -@@ -66,6 +66,15 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, - dev->split_hubport = split_hubport; - dev->split_hubaddr = split_hubaddr; - -+ if (controller->dev->attach_dev) { -+ err = controller->dev->attach_dev (controller, dev); -+ if (err) -+ { -+ grub_free (dev); -+ return NULL; -+ } -+ } -+ - err = grub_usb_device_initialize (dev); - if (err) - { -@@ -405,6 +414,8 @@ static void - detach_device (grub_usb_device_t dev) - { - unsigned i; -+ grub_usb_err_t err; -+ - int k; - if (!dev) - return; -@@ -425,6 +436,14 @@ detach_device (grub_usb_device_t dev) - if (inter && inter->detach_hook) - inter->detach_hook (dev, i, k); - } -+ if (dev->controller.dev->detach_dev) { -+ err = dev->controller.dev->detach_dev (&dev->controller, dev); -+ if (err) -+ { -+ // XXX -+ } -+ } -+ - grub_usb_devs[dev->addr] = 0; - } - -diff --git a/include/grub/usb.h b/include/grub/usb.h -index ea6ee8c2c..4dd179db2 100644 ---- a/include/grub/usb.h -+++ b/include/grub/usb.h -@@ -126,6 +126,10 @@ struct grub_usb_controller_dev - - grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed); - -+ grub_usb_err_t (*attach_dev) (grub_usb_controller_t ctrl, grub_usb_device_t dev); -+ -+ grub_usb_err_t (*detach_dev) (grub_usb_controller_t ctrl, grub_usb_device_t dev); -+ - /* Per controller flag - port reset pending, don't do another reset */ - grub_uint64_t pending_reset; - --- -2.39.5 - diff --git a/config/grub/xhci/patches/0018-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch b/config/grub/xhci/patches/0018-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch deleted file mode 100644 index d2067637..00000000 --- a/config/grub/xhci/patches/0018-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 7db1cdd1cdbb79a8da04648dcbf7318d200f72a4 Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Mon, 7 Dec 2020 08:41:25 +0100 -Subject: [PATCH 18/26] grub-core/bus/usb/usbhub: Add new private fields for - xHCI controller - -Store the root port number, the route, consisting out of the port ID -in each nibble, and a pointer to driver private data. - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> ---- - grub-core/bus/usb/usbhub.c | 11 ++++++++--- - include/grub/usb.h | 5 +++++ - 2 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c -index 8e963e84b..b4b3a1a61 100644 ---- a/grub-core/bus/usb/usbhub.c -+++ b/grub-core/bus/usb/usbhub.c -@@ -49,7 +49,9 @@ static grub_usb_controller_dev_t grub_usb_list; - static grub_usb_device_t - grub_usb_hub_add_dev (grub_usb_controller_t controller, - grub_usb_speed_t speed, -- int split_hubport, int split_hubaddr) -+ int split_hubport, int split_hubaddr, -+ int root_portno, -+ grub_uint32_t route) - { - grub_usb_device_t dev; - int i; -@@ -65,6 +67,8 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, - dev->speed = speed; - dev->split_hubport = split_hubport; - dev->split_hubaddr = split_hubaddr; -+ dev->root_port = root_portno; -+ dev->route = route; - - if (controller->dev->attach_dev) { - err = controller->dev->attach_dev (controller, dev); -@@ -245,7 +249,7 @@ attach_root_port (struct grub_usb_hub *hub, int portno, - and full/low speed device connected to OHCI/UHCI needs not - transaction translation - e.g. hubport and hubaddr should be - always none (zero) for any device connected to any root hub. */ -- dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0); -+ dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0, portno, 0); - hub->controller->dev->pending_reset = 0; - npending--; - if (! dev) -@@ -676,7 +680,8 @@ poll_nonroot_hub (grub_usb_device_t dev) - - /* Add the device and assign a device address to it. */ - next_dev = grub_usb_hub_add_dev (&dev->controller, speed, -- split_hubport, split_hubaddr); -+ split_hubport, split_hubaddr, dev->root_port, -+ dev->route << 4 | (i & 0xf)); - if (dev->controller.dev->pending_reset) - { - dev->controller.dev->pending_reset = 0; -diff --git a/include/grub/usb.h b/include/grub/usb.h -index 4dd179db2..609faf7d0 100644 ---- a/include/grub/usb.h -+++ b/include/grub/usb.h -@@ -237,6 +237,11 @@ struct grub_usb_device - int split_hubport; - - int split_hubaddr; -+ -+ /* xHCI specific information */ -+ int root_port; -+ grub_uint32_t route; -+ void *xhci_priv; - }; - - --- -2.39.5 - diff --git a/config/grub/xhci/patches/0019-grub-core-bus-usb-Add-xhci-support.patch b/config/grub/xhci/patches/0019-grub-core-bus-usb-Add-xhci-support.patch deleted file mode 100644 index b4d6e956..00000000 --- a/config/grub/xhci/patches/0019-grub-core-bus-usb-Add-xhci-support.patch +++ /dev/null @@ -1,2807 +0,0 @@ -From 6b34ac2449362da5139e702e484a432d828a505d Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Mon, 7 Dec 2020 08:41:26 +0100 -Subject: [PATCH 19/26] grub-core/bus/usb: Add xhci support - -Add support for xHCI USB controllers. -The code is based on seabios implementation, but has been heavily -modified to match grubs internals. - -Changes done in version 2: -* Code cleanup -* Code style fixes -* Don't leak memory buffers -* Compile without warnings -* Add more defines -* Add more helper functions -* Don't assume a 1:1 virtual to physical mapping -* Flush cachelines after writing buffers -* Don't use hardcoded page size -* Proper scratchpad register setup -* xHCI bios ownership handoff - -Changes done in version 3: -* Fixed a race condition detecting events, which doesn't appear on - qemu based xHCI controllers -* Don't accidently disable USB3.0 devices after first command -* Support arbitrary protocol speed IDs -* Coding style cleanup - -Tested: -* Qemu system x86_64 - * virtual USB HID keyboard (usb-kbd) - * virtual USB HID mass storage (usb-storage) -* init Supermicro X11SSH-F - * iKVM HID keyboard - * USB3 HID mass storage (controller root port) - * USB HID keyboard - -TODO: - * Test on more hardware - * Test on USB3 hubs - * Support for USB 3.1 and USB 3.2 controllers - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> -Signed-off-by: sylv <sylv@sylv.io> ---- - Makefile.am | 2 +- - grub-core/Makefile.core.def | 7 + - grub-core/bus/usb/xhci-pci.c | 195 +++ - grub-core/bus/usb/xhci.c | 2496 ++++++++++++++++++++++++++++++++++ - include/grub/usb.h | 4 + - 5 files changed, 2703 insertions(+), 1 deletion(-) - create mode 100644 grub-core/bus/usb/xhci-pci.c - create mode 100644 grub-core/bus/usb/xhci.c - -diff --git a/Makefile.am b/Makefile.am -index 43635d5ff..65016f856 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -434,7 +434,7 @@ if COND_i386_coreboot - FS_PAYLOAD_MODULES ?= $(shell cat grub-core/fs.lst) - default_payload.elf: grub-mkstandalone grub-mkimage FORCE - test -f $@ && rm $@ || true -- pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg -+ pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata xhci ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg - endif - - endif -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index cd29a9df8..d3947739f 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -667,6 +667,13 @@ module = { - enable = arm_coreboot; - }; - -+module = { -+ name = xhci; -+ common = bus/usb/xhci.c; -+ pci = bus/usb/xhci-pci.c; -+ enable = pci; -+}; -+ - module = { - name = pci; - common = bus/pci.c; -diff --git a/grub-core/bus/usb/xhci-pci.c b/grub-core/bus/usb/xhci-pci.c -new file mode 100644 -index 000000000..a5bd3c97d ---- /dev/null -+++ b/grub-core/bus/usb/xhci-pci.c -@@ -0,0 +1,195 @@ -+/* xhci.c - XHCI Support. */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 9elements Cyber Security -+ * -+ * 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/pci.h> -+#include <grub/cpu/pci.h> -+#include <grub/cs5536.h> -+#include <grub/misc.h> -+#include <grub/mm.h> -+#include <grub/time.h> -+#include <grub/usb.h> -+ -+#define GRUB_XHCI_PCI_SBRN_REG 0x60 -+#define GRUB_XHCI_ADDR_MEM_MASK (~0xff) -+ -+/* USBLEGSUP bits and related OS OWNED byte offset */ -+enum -+{ -+ GRUB_XHCI_BIOS_OWNED = (1 << 16), -+ GRUB_XHCI_OS_OWNED = (1 << 24) -+}; -+ -+/* PCI iteration function... */ -+static int -+grub_xhci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, -+ void *data __attribute__ ((unused))) -+{ -+ volatile grub_uint32_t *regs; -+ grub_uint32_t base, base_h; -+ grub_uint32_t eecp_offset; -+ grub_uint32_t usblegsup = 0; -+ grub_uint64_t maxtime; -+ grub_uint32_t interf; -+ grub_uint32_t subclass; -+ grub_uint32_t class; -+ grub_uint8_t release; -+ grub_uint32_t class_code; -+ -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: begin\n"); -+ -+ if (pciid == GRUB_CS5536_PCIID) -+ { -+ grub_dprintf ("xhci", "CS5536 not supported\n"); -+ return 0; -+ } -+ else -+ { -+ grub_pci_address_t addr; -+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); -+ class_code = grub_pci_read (addr) >> 8; -+ interf = class_code & 0xFF; -+ subclass = (class_code >> 8) & 0xFF; -+ class = class_code >> 16; -+ -+ /* If this is not an XHCI controller, just return. */ -+ if (class != 0x0c || subclass != 0x03 || interf != 0x30) -+ return 0; -+ -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: class OK\n"); -+ -+ /* Check Serial Bus Release Number */ -+ addr = grub_pci_make_address (dev, GRUB_XHCI_PCI_SBRN_REG); -+ release = grub_pci_read_byte (addr); -+ if (release != 0x30) -+ { -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: Wrong SBRN: %0x\n", -+ release); -+ return 0; -+ } -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: bus rev. num. OK\n"); -+ -+ /* Determine XHCI XHCC registers base address. */ -+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); -+ base = grub_pci_read (addr); -+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); -+ base_h = grub_pci_read (addr); -+ /* Stop if registers are mapped above 4G - GRUB does not currently -+ * work with registers mapped above 4G */ -+ if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32) -+ && (base_h != 0)) -+ { -+ grub_dprintf ("xhci", -+ "XHCI grub_xhci_pci_iter: registers above 4G are not supported\n"); -+ return 0; -+ } -+ base &= GRUB_PCI_ADDR_MEM_MASK; -+ if (!base) -+ { -+ grub_dprintf ("xhci", -+ "XHCI: XHCI is not mapped\n"); -+ return 0; -+ } -+ -+ /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */ -+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); -+ grub_pci_write_word(addr, -+ GRUB_PCI_COMMAND_MEM_ENABLED -+ | GRUB_PCI_COMMAND_BUS_MASTER -+ | grub_pci_read_word(addr)); -+ -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: 32-bit XHCI OK\n"); -+ } -+ -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: iobase of XHCC: %08x\n", -+ (base & GRUB_XHCI_ADDR_MEM_MASK)); -+ -+ regs = grub_pci_device_map_range (dev, -+ (base & GRUB_XHCI_ADDR_MEM_MASK), -+ 0x100); -+ -+ /* Is there EECP ? */ -+ eecp_offset = (grub_le_to_cpu32 (regs[2]) >> 8) & 0xff; -+ -+ /* Determine and change ownership. */ -+ /* EECP offset valid in HCCPARAMS */ -+ /* Ownership can be changed via EECP only */ -+ if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40) -+ { -+ grub_pci_address_t pciaddr_eecp; -+ pciaddr_eecp = grub_pci_make_address (dev, eecp_offset); -+ -+ usblegsup = grub_pci_read (pciaddr_eecp); -+ if (usblegsup & GRUB_XHCI_BIOS_OWNED) -+ { -+ grub_boot_time ("Taking ownership of XHCI controller"); -+ grub_dprintf ("xhci", -+ "XHCI grub_xhci_pci_iter: XHCI owned by: BIOS\n"); -+ /* Ownership change - set OS_OWNED bit */ -+ grub_pci_write (pciaddr_eecp, usblegsup | GRUB_XHCI_OS_OWNED); -+ /* Ensure PCI register is written */ -+ grub_pci_read (pciaddr_eecp); -+ -+ /* Wait for finish of ownership change, XHCI specification -+ * doesn't say how long it can take... */ -+ maxtime = grub_get_time_ms () + 1000; -+ while ((grub_pci_read (pciaddr_eecp) & GRUB_XHCI_BIOS_OWNED) -+ && (grub_get_time_ms () < maxtime)); -+ if (grub_pci_read (pciaddr_eecp) & GRUB_XHCI_BIOS_OWNED) -+ { -+ grub_dprintf ("xhci", -+ "XHCI grub_xhci_pci_iter: XHCI change ownership timeout"); -+ /* Change ownership in "hard way" - reset BIOS ownership */ -+ grub_pci_write (pciaddr_eecp, GRUB_XHCI_OS_OWNED); -+ /* Ensure PCI register is written */ -+ grub_pci_read (pciaddr_eecp); -+ } -+ } -+ else if (usblegsup & GRUB_XHCI_OS_OWNED) -+ /* XXX: What to do in this case - nothing ? Can it happen ? */ -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: XHCI owned by: OS\n"); -+ else -+ { -+ grub_dprintf ("xhci", -+ "XHCI grub_Xhci_pci_iter: XHCI owned by: NONE\n"); -+ /* XXX: What to do in this case ? Can it happen ? -+ * Is code below correct ? */ -+ /* Ownership change - set OS_OWNED bit */ -+ grub_pci_write (pciaddr_eecp, GRUB_XHCI_OS_OWNED); -+ /* Ensure PCI register is written */ -+ grub_pci_read (pciaddr_eecp); -+ } -+ -+ /* Disable SMI, just to be sure. */ -+ pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); -+ grub_pci_write (pciaddr_eecp, 0); -+ /* Ensure PCI register is written */ -+ grub_pci_read (pciaddr_eecp); -+ } -+ -+ grub_dprintf ("xhci", "inithw: XHCI grub_xhci_pci_iter: ownership OK\n"); -+ -+ grub_xhci_init_device (regs); -+ return 0; -+} -+ -+void -+grub_xhci_pci_scan (void) -+{ -+ grub_pci_iterate (grub_xhci_pci_iter, NULL); -+} -diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c -new file mode 100644 -index 000000000..f4591ffb5 ---- /dev/null -+++ b/grub-core/bus/usb/xhci.c -@@ -0,0 +1,2496 @@ -+/* xhci.c - XHCI Support. */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2020 9elements Cyber Security -+ * -+ * 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/>. -+ * -+ * Big parts of this software are inspired by seabios XHCI implementation -+ * Released under LGPLv3. Credits to: -+ * -+ * Copyright (C) 2013 Gerd Hoffmann <kraxel@redhat.com> -+ * Copyright (C) 2014 Kevin O'Connor <kevin@koconnor.net> -+ */ -+ -+#include <grub/dl.h> -+#include <grub/err.h> -+#include <grub/mm.h> -+#include <grub/usb.h> -+#include <grub/usbtrans.h> -+#include <grub/misc.h> -+#include <grub/time.h> -+#include <grub/loader.h> -+#include <grub/disk.h> -+#include <grub/dma.h> -+#include <grub/cache.h> -+#include <grub/i386/cpuid.h> -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+/* This simple GRUB implementation of XHCI driver */ -+/* Based on the specification -+ * "eXtensible Host Controller Interface for Universal Serial Bus" Revision 1.2 -+ */ -+ -+ -+#define xhci_get_field(data, field) \ -+ (((data) >> field##_SHIFT) & field##_MASK) -+#define XHCI_PORTSC_PLS_MASK 0xf -+#define XHCI_PORTSC_PLS_SHIFT 5 -+#define XHCI_PORTSC_SPEED_MASK 0xf -+#define XHCI_PORTSC_SPEED_SHIFT 10 -+ -+enum -+{ -+ XHCI_USB_FULLSPEED = 1, -+ XHCI_USB_LOWSPEED, -+ XHCI_USB_HIGHSPEED, -+ XHCI_USB_SUPERSPEED -+}; -+ -+/* Chapter 5.3 Host Controller Capability Registers */ -+struct grub_xhci_caps { -+ grub_uint8_t caplength; -+ grub_uint8_t reserved_01; -+ grub_uint16_t hciversion; -+ grub_uint32_t hcsparams1; -+ grub_uint32_t hcsparams2; -+ grub_uint32_t hcsparams3; -+ grub_uint32_t hccparams; -+ grub_uint32_t dboff; -+ grub_uint32_t rtsoff; -+ grub_uint32_t hccparams2; -+} GRUB_PACKED; -+ -+/* extended capabilities */ -+struct grub_xhci_xcap { -+ grub_uint32_t cap; -+ grub_uint32_t data[]; -+} GRUB_PACKED; -+ -+#define XHCI_CAP_LEGACY_SUPPORT 1 -+#define XHCI_CAP_SUPPORTED_PROTOCOL 2 -+ -+struct xhci_portmap { -+ grub_uint8_t start; -+ grub_uint8_t count; -+} GRUB_PACKED; -+ -+struct grub_xhci_op { -+ grub_uint32_t usbcmd; -+ grub_uint32_t usbsts; -+ grub_uint32_t pagesize; -+ grub_uint32_t reserved_01[2]; -+ grub_uint32_t dnctl; -+ grub_uint32_t crcr_low; -+ grub_uint32_t crcr_high; -+ grub_uint32_t reserved_02[4]; -+ grub_uint32_t dcbaap_low; -+ grub_uint32_t dcbaap_high; -+ grub_uint32_t config; -+} GRUB_PACKED; -+ -+enum -+{ -+ GRUB_XHCI_CMD_RS = (1<<0), -+ GRUB_XHCI_CMD_HCRST = (1<<1), -+ GRUB_XHCI_CMD_INTE = (1<<2), -+ GRUB_XHCI_CMD_HSEE = (1<<3), -+ GRUB_XHCI_CMD_LHCRST = (1<<7), -+ GRUB_XHCI_CMD_CSS = (1<<8), -+ GRUB_XHCI_CMD_CRS = (1<<9), -+ GRUB_XHCI_CMD_EWE = (1<<10), -+ GRUB_XHCI_CMD_EU3S = (1<<11) -+}; -+ -+enum -+{ -+ GRUB_XHCI_STS_HCH = (1<<0), -+ GRUB_XHCI_STS_HSE = (1<<2), -+ GRUB_XHCI_STS_EINT = (1<<3), -+ GRUB_XHCI_STS_PCD = (1<<4), -+ GRUB_XHCI_STS_SSS = (1<<8), -+ GRUB_XHCI_STS_RSS = (1<<9), -+ GRUB_XHCI_STS_SRE = (1<<10), -+ GRUB_XHCI_STS_CNR = (1<<11), -+ GRUB_XHCI_STS_HCE = (1<<12) -+}; -+ -+ -+/* Port Registers Offset */ -+#define GRUB_XHCI_PR_OFFSET 0x400 -+/* Interrupter Registers Offset */ -+#define GRUB_XHCI_IR_OFFSET 0x20 -+ -+/* Port Status and Control registers offsets */ -+ -+/* Chapter 6 Data Structures */ -+#define ALIGN_SPBA 64 -+#define ALIGN_DCBAA 64 -+#define ALIGN_CMD_RING_SEG 64 -+#define ALIGN_EVT_RING_SEG 64 -+#define ALIGN_EVT_RING_TABLE 64 -+#define ALIGN_TRB 16 -+#define ALIGN_INCTX 64 -+#define ALIGN_SLOTCTX 32 -+ -+#define BOUNDARY_RING 0x10000 -+ -+enum -+{ -+ GRUB_XHCI_PORTSC_CCS = (1<<0), -+ GRUB_XHCI_PORTSC_PED = (1<<1), -+ GRUB_XHCI_PORTSC_OCA = (1<<3), -+ GRUB_XHCI_PORTSC_PR = (1<<4), -+ GRUB_XHCI_PORTSC_PP = (1<<9), -+ GRUB_XHCI_PORTSC_SPEED_FULL = (1<<10), -+ GRUB_XHCI_PORTSC_SPEED_LOW = (2<<10), -+ GRUB_XHCI_PORTSC_SPEED_HIGH = (3<<10), -+ GRUB_XHCI_PORTSC_SPEED_SUPER = (4<<10), -+ GRUB_XHCI_PORTSC_LWS = (1<<16), -+ GRUB_XHCI_PORTSC_CSC = (1<<17), -+ GRUB_XHCI_PORTSC_PEC = (1<<18), -+ GRUB_XHCI_PORTSC_WRC = (1<<19), -+ GRUB_XHCI_PORTSC_OCC = (1<<20), -+ GRUB_XHCI_PORTSC_PRC = (1<<21), -+ GRUB_XHCI_PORTSC_PLC = (1<<22), -+ GRUB_XHCI_PORTSC_CEC = (1<<23), -+ GRUB_XHCI_PORTSC_CAS = (1<<24), -+ GRUB_XHCI_PORTSC_WCE = (1<<25), -+ GRUB_XHCI_PORTSC_WDE = (1<<26), -+ GRUB_XHCI_PORTSC_WOE = (1<<27), -+ GRUB_XHCI_PORTSC_DR = (1<<30), -+ GRUB_XHCI_PORTSC_WPR = (1<<31) -+}; -+ -+/* XHCI memory data structs */ -+#define GRUB_XHCI_MAX_ENDPOINTS 32 -+ -+#define GRUB_XHCI_RING_ITEMS 128 -+#define GRUB_XHCI_RING_SIZE (GRUB_XHCI_RING_ITEMS*sizeof(struct grub_xhci_trb)) -+/* -+ * xhci_ring structs are allocated with XHCI_RING_SIZE alignment, -+ * then we can get it from a trb pointer (provided by evt ring). -+ */ -+#define XHCI_RING(_trb) \ -+ ((struct grub_xhci_ring*)((grub_uint32_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1))) -+ -+/* slot context */ -+struct grub_xhci_slotctx { -+ grub_uint32_t ctx[4]; -+ grub_uint32_t reserved_01[4]; -+} GRUB_PACKED; -+ -+/* endpoint context */ -+struct grub_xhci_epctx { -+ grub_uint32_t ctx[2]; -+ grub_uint32_t deq_low; -+ grub_uint32_t deq_high; -+ grub_uint32_t length; -+ grub_uint32_t reserved_01[3]; -+} GRUB_PACKED; -+ -+/* device context array element */ -+struct grub_xhci_devlist { -+ grub_uint32_t ptr_low; -+ grub_uint32_t ptr_high; -+} GRUB_PACKED; -+ -+/* input context */ -+struct grub_xhci_inctx { -+ grub_uint32_t del; -+ grub_uint32_t add; -+ grub_uint32_t reserved_01[6]; -+} GRUB_PACKED; -+ -+/* transfer block (ring element) */ -+struct grub_xhci_trb { -+ grub_uint32_t ptr_low; -+ grub_uint32_t ptr_high; -+ grub_uint32_t status; -+ grub_uint32_t control; -+} GRUB_PACKED; -+ -+#define TRB_C (1<<0) -+#define TRB_TYPE_SHIFT 10 -+#define TRB_TYPE_MASK 0x3f -+#define TRB_TYPE(t) (((t) >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) -+ -+#define TRB_EV_ED (1<<2) -+ -+#define TRB_TR_ENT (1<<1) -+#define TRB_TR_ISP (1<<2) -+#define TRB_TR_NS (1<<3) -+#define TRB_TR_CH (1<<4) -+#define TRB_TR_IOC (1<<5) -+#define TRB_TR_IDT (1<<6) -+#define TRB_TR_TBC_SHIFT 7 -+#define TRB_TR_TBC_MASK 0x3 -+#define TRB_TR_BEI (1<<9) -+#define TRB_TR_TLBPC_SHIFT 16 -+#define TRB_TR_TLBPC_MASK 0xf -+#define TRB_TR_FRAMEID_SHIFT 20 -+#define TRB_TR_FRAMEID_MASK 0x7ff -+#define TRB_TR_SIA (1<<31) -+ -+#define TRB_TR_DIR (1<<16) -+ -+#define TRB_CR_SLOTID_SHIFT 24 -+#define TRB_CR_SLOTID_MASK 0xff -+#define TRB_CR_EPID_SHIFT 16 -+#define TRB_CR_EPID_MASK 0x1f -+ -+#define TRB_CR_BSR (1<<9) -+#define TRB_CR_DC (1<<9) -+ -+#define TRB_LK_TC (1<<1) -+ -+#define TRB_INTR_SHIFT 22 -+#define TRB_INTR_MASK 0x3ff -+#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) -+ -+typedef enum TRBType { -+ TRB_RESERVED = 0, -+ TR_NORMAL, -+ TR_SETUP, -+ TR_DATA, -+ TR_STATUS, -+ TR_ISOCH, -+ TR_LINK, -+ TR_EVDATA, -+ TR_NOOP, -+ CR_ENABLE_SLOT, -+ CR_DISABLE_SLOT, -+ CR_ADDRESS_DEVICE, -+ CR_CONFIGURE_ENDPOINT, -+ CR_EVALUATE_CONTEXT, -+ CR_RESET_ENDPOINT, -+ CR_STOP_ENDPOINT, -+ CR_SET_TR_DEQUEUE, -+ CR_RESET_DEVICE, -+ CR_FORCE_EVENT, -+ CR_NEGOTIATE_BW, -+ CR_SET_LATENCY_TOLERANCE, -+ CR_GET_PORT_BANDWIDTH, -+ CR_FORCE_HEADER, -+ CR_NOOP, -+ ER_TRANSFER = 32, -+ ER_COMMAND_COMPLETE, -+ ER_PORT_STATUS_CHANGE, -+ ER_BANDWIDTH_REQUEST, -+ ER_DOORBELL, -+ ER_HOST_CONTROLLER, -+ ER_DEVICE_NOTIFICATION, -+ ER_MFINDEX_WRAP, -+} TRBType; -+ -+typedef enum TRBCCode { -+ CC_INVALID = 0, -+ CC_SUCCESS, -+ CC_DATA_BUFFER_ERROR, -+ CC_BABBLE_DETECTED, -+ CC_USB_TRANSACTION_ERROR, -+ CC_TRB_ERROR, -+ CC_STALL_ERROR, -+ CC_RESOURCE_ERROR, -+ CC_BANDWIDTH_ERROR, -+ CC_NO_SLOTS_ERROR, -+ CC_INVALID_STREAM_TYPE_ERROR, -+ CC_SLOT_NOT_ENABLED_ERROR, -+ CC_EP_NOT_ENABLED_ERROR, -+ CC_SHORT_PACKET, -+ CC_RING_UNDERRUN, -+ CC_RING_OVERRUN, -+ CC_VF_ER_FULL, -+ CC_PARAMETER_ERROR, -+ CC_BANDWIDTH_OVERRUN, -+ CC_CONTEXT_STATE_ERROR, -+ CC_NO_PING_RESPONSE_ERROR, -+ CC_EVENT_RING_FULL_ERROR, -+ CC_INCOMPATIBLE_DEVICE_ERROR, -+ CC_MISSED_SERVICE_ERROR, -+ CC_COMMAND_RING_STOPPED, -+ CC_COMMAND_ABORTED, -+ CC_STOPPED, -+ CC_STOPPED_LENGTH_INVALID, -+ CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, -+ CC_ISOCH_BUFFER_OVERRUN = 31, -+ CC_EVENT_LOST_ERROR, -+ CC_UNDEFINED_ERROR, -+ CC_INVALID_STREAM_ID_ERROR, -+ CC_SECONDARY_BANDWIDTH_ERROR, -+ CC_SPLIT_TRANSACTION_ERROR -+} TRBCCode; -+ -+enum { -+ PLS_U0 = 0, -+ PLS_U1 = 1, -+ PLS_U2 = 2, -+ PLS_U3 = 3, -+ PLS_DISABLED = 4, -+ PLS_RX_DETECT = 5, -+ PLS_INACTIVE = 6, -+ PLS_POLLING = 7, -+ PLS_RECOVERY = 8, -+ PLS_HOT_RESET = 9, -+ PLS_COMPILANCE_MODE = 10, -+ PLS_TEST_MODE = 11, -+ PLS_RESUME = 15, -+}; -+ -+/* event ring segment */ -+struct grub_xhci_er_seg { -+ grub_uint32_t ptr_low; -+ grub_uint32_t ptr_high; -+ grub_uint32_t size; -+ grub_uint32_t reserved_01; -+} GRUB_PACKED; -+ -+struct grub_xhci_ring { -+ struct grub_xhci_trb ring[GRUB_XHCI_RING_ITEMS]; -+ struct grub_xhci_trb evt; -+ grub_uint32_t eidx; -+ grub_uint32_t nidx; -+ grub_uint32_t cs; -+}; -+ -+/* port registers */ -+struct grub_xhci_pr { -+ grub_uint32_t portsc; -+ grub_uint32_t portpmsc; -+ grub_uint32_t portli; -+ grub_uint32_t reserved_01; -+} GRUB_PACKED; -+ -+/* doorbell registers */ -+struct grub_xhci_db { -+ grub_uint32_t doorbell; -+} GRUB_PACKED; -+ -+/* runtime registers */ -+struct grub_xhci_rts { -+ grub_uint32_t mfindex; -+} GRUB_PACKED; -+ -+/* interrupter registers */ -+struct grub_xhci_ir { -+ grub_uint32_t iman; -+ grub_uint32_t imod; -+ grub_uint32_t erstsz; -+ grub_uint32_t reserved_01; -+ grub_uint32_t erstba_low; -+ grub_uint32_t erstba_high; -+ grub_uint32_t erdp_low; -+ grub_uint32_t erdp_high; -+} GRUB_PACKED; -+ -+struct grub_xhci_psid { -+ grub_uint8_t id; -+ grub_uint8_t psie; -+ grub_uint16_t psim; -+ grub_uint64_t bitrate; -+ grub_usb_speed_t grub_usb_speed; -+}; -+ -+struct grub_xhci_psids { -+ grub_uint8_t major; -+ grub_uint8_t minor; -+ struct grub_xhci_psid psids[16]; -+}; -+ -+struct grub_xhci -+{ -+ grub_uint8_t shutdown; /* 1 if preparing shutdown of controller */ -+ /* xhci registers */ -+ volatile struct grub_xhci_caps *caps; /* Capability registers */ -+ volatile struct grub_xhci_op *op; /* Operational registers */ -+ volatile struct grub_xhci_pr *pr; /* Port Registers */ -+ volatile struct grub_xhci_db *db; /* doorbell */ -+ volatile struct grub_xhci_ir *ir; /* Interrupt Registers */ -+ /* devinfo */ -+ grub_uint32_t xcap; -+ grub_uint32_t ports; -+ grub_uint32_t slots; -+ grub_uint8_t flag64; -+ grub_uint16_t spb; -+ grub_uint32_t pagesize; -+ struct xhci_portmap usb2; -+ struct xhci_portmap usb3; -+ struct grub_xhci_psids *psids; -+ /* xhci data structures */ -+ struct grub_pci_dma_chunk *devs_dma; -+ volatile struct grub_xhci_devlist *devs; -+ struct grub_pci_dma_chunk *cmds_dma; -+ volatile struct grub_xhci_ring *cmds; -+ struct grub_pci_dma_chunk *evts_dma; -+ volatile struct grub_xhci_ring *evts; -+ struct grub_pci_dma_chunk *eseg_dma; -+ volatile struct grub_xhci_er_seg *eseg; -+ struct grub_pci_dma_chunk *spba_dma; -+ struct grub_pci_dma_chunk *spad_dma; -+ -+ struct grub_xhci *next; -+}; -+ -+struct grub_xhci_priv { -+ grub_uint8_t slotid; -+ grub_uint32_t max_packet; -+ struct grub_pci_dma_chunk *enpoint_trbs_dma[32]; -+ volatile struct grub_xhci_ring *enpoint_trbs[32]; -+ struct grub_pci_dma_chunk *slotctx_dma; -+}; -+ -+struct grub_xhci_port { -+ grub_uint32_t portsc; -+ grub_uint32_t portpmsc; -+ grub_uint32_t portli; -+ grub_uint32_t reserved_01; -+}; -+ -+struct grub_xhci_transfer_controller_data { -+ grub_uint32_t transfer_size; -+}; -+ -+static struct grub_xhci *xhci; -+ -+/**************************************************************** -+ * general access functions -+ ****************************************************************/ -+ -+static inline void -+grub_xhci_write32(volatile void *addr, grub_uint32_t val) { -+ *(volatile grub_uint32_t *)addr = val; -+} -+static inline void -+grub_xhci_write16(volatile void *addr, grub_uint16_t val) { -+ *(volatile grub_uint16_t *)addr = val; -+} -+static inline void -+grub_xhci_write8(void *addr, grub_uint8_t val) { -+ *(volatile grub_uint8_t *)addr = val; -+} -+ -+static inline grub_uint32_t -+grub_xhci_read32(volatile void *addr) { -+ return grub_le_to_cpu32 (*((volatile grub_uint32_t *)addr)); -+} -+ -+static inline grub_uint16_t -+grub_xhci_read16(volatile void *addr) { -+ return grub_le_to_cpu16 (*((volatile grub_uint32_t *)addr)); -+} -+static inline grub_uint8_t -+grub_xhci_read8(volatile void *addr) { -+ return (*((volatile grub_uint32_t *)addr)); -+} -+ -+static inline grub_uint32_t -+grub_xhci_port_read (struct grub_xhci *x, grub_uint32_t port) -+{ -+ return grub_xhci_read32(&x->pr[port].portsc); -+} -+ -+static inline void -+grub_xhci_port_write (struct grub_xhci *x, grub_uint32_t port, -+ grub_uint32_t and_mask, grub_uint32_t or_mask) -+{ -+ grub_uint32_t reg = grub_xhci_port_read(x, port); -+ reg &= and_mask; -+ reg |= or_mask; -+ -+ grub_xhci_write32(&x->pr[port].portsc, reg); -+} -+ -+/**************************************************************** -+ * xhci status and support functions -+ ****************************************************************/ -+ -+static grub_uint32_t xhci_get_pagesize(struct grub_xhci *x) -+{ -+ /* Chapter 5.4.3 Page Size Register (PAGESIZE) */ -+ for (grub_uint8_t i = 0; i < 16; i++) -+ { -+ if (grub_xhci_read32(&x->op->pagesize) & (1 << i)) -+ return 1 << (12 + i); -+ } -+ return 0; -+} -+ -+static grub_uint8_t xhci_is_halted(struct grub_xhci *x) -+{ -+ return !!(grub_xhci_read32(&x->op->usbsts) & 1); -+} -+ -+/* Just for debugging */ -+static void xhci_check_status(struct grub_xhci *x) -+{ -+ grub_uint32_t reg; -+ -+ reg = grub_xhci_read32(&x->op->usbsts); -+ if (reg & 1) -+ grub_dprintf("xhci", "%s: xHCI halted\n", __func__); -+ if (reg & 2) -+ grub_dprintf("xhci", "%s: Host system error detected\n", __func__); -+ if (reg & (1 << 12)) -+ grub_dprintf("xhci", "%s: Internal error detected\n", __func__); -+ reg = grub_xhci_read32(&x->op->crcr_low); -+ if (reg & (1 << 3)) -+ grub_dprintf("xhci", "%s: Command ring running\n", __func__); -+} -+ -+/* xhci_memalign_dma32 allocates DMA memory satisfying alignment and boundary -+ * requirements without wasting to much memory */ -+static struct grub_pci_dma_chunk * -+xhci_memalign_dma32(grub_size_t align, -+ grub_size_t size, -+ grub_size_t boundary) -+{ -+ struct grub_pci_dma_chunk *tmp; -+ const grub_uint32_t mask = boundary - 1; -+ grub_uint32_t start, end; -+ -+ /* Allocate some memory and check if it doesn't cross boundary */ -+ tmp = grub_memalign_dma32(align, size); -+ start = grub_dma_get_phys(tmp); -+ end = start + size - 1; -+ if ((start & mask) == (end & mask)) -+ return tmp; -+ /* Buffer isn't usable, allocate bigger one */ -+ grub_dma_free(tmp); -+ -+ return grub_memalign_dma32(boundary, size); -+} -+ -+/**************************************************************** -+ * helper functions for in context DMA buffer -+ ****************************************************************/ -+ -+static int -+grub_xhci_inctx_size(struct grub_xhci *x) -+{ -+ const grub_uint8_t cnt = GRUB_XHCI_MAX_ENDPOINTS + 1; -+ return (sizeof(struct grub_xhci_inctx) * cnt) << x->flag64; -+} -+ -+static void -+grub_xhci_inctx_sync_dma_caches(struct grub_xhci *x, struct grub_pci_dma_chunk *inctx) -+{ -+ grub_arch_sync_dma_caches(inctx, grub_xhci_inctx_size(x)); -+} -+ -+static struct grub_pci_dma_chunk * -+grub_xhci_alloc_inctx(struct grub_xhci *x, int maxepid, -+ struct grub_usb_device *dev) -+{ -+ int size = grub_xhci_inctx_size(x); -+ struct grub_pci_dma_chunk *dma = xhci_memalign_dma32(ALIGN_INCTX, size, -+ x->pagesize); -+ if (!dma) -+ return NULL; -+ -+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(dma); -+ grub_memset((void *)in, 0, size); -+ -+ struct grub_xhci_slotctx *slot = (void*)&in[1 << x->flag64]; -+ slot->ctx[0] |= maxepid << 27; /* context entries */ -+ grub_dprintf("xhci", "%s: speed=%d root_port=%d\n", __func__, dev->speed, dev->root_port); -+ switch (dev->speed) { -+ case GRUB_USB_SPEED_FULL: -+ slot->ctx[0] |= XHCI_USB_FULLSPEED << 20; -+ break; -+ case GRUB_USB_SPEED_HIGH: -+ slot->ctx[0] |= XHCI_USB_HIGHSPEED << 20; -+ break; -+ case GRUB_USB_SPEED_LOW: -+ slot->ctx[0] |= XHCI_USB_LOWSPEED << 20; -+ break; -+ case GRUB_USB_SPEED_SUPER: -+ slot->ctx[0] |= XHCI_USB_SUPERSPEED << 20; -+ break; -+ case GRUB_USB_SPEED_NONE: -+ slot->ctx[0] |= 0 << 20; -+ break; -+ } -+ -+ /* Route is greater zero on devices that are connected to a non root hub */ -+ if (dev->route) -+ { -+ /* FIXME: Implement this code for non SuperSpeed hub devices */ -+ } -+ slot->ctx[0] |= dev->route; -+ slot->ctx[1] |= (dev->root_port+1) << 16; -+ -+ grub_arch_sync_dma_caches(in, size); -+ -+ return dma; -+} -+ -+/**************************************************************** -+ * xHCI event processing -+ ****************************************************************/ -+ -+/* Dequeue events on the XHCI event ring generated by the hardware */ -+static void xhci_process_events(struct grub_xhci *x) -+{ -+ volatile struct grub_xhci_ring *evts = x->evts; -+ /* XXX invalidate caches */ -+ -+ for (;;) { -+ /* check for event */ -+ grub_uint32_t nidx = grub_xhci_read32(&evts->nidx); -+ grub_uint32_t cs = grub_xhci_read32(&evts->cs); -+ volatile struct grub_xhci_trb *etrb = evts->ring + nidx; -+ grub_uint32_t control = grub_xhci_read32(&etrb->control); -+ if ((control & TRB_C) != (cs ? 1 : 0)) -+ return; -+ -+ /* process event */ -+ grub_uint32_t evt_type = TRB_TYPE(control); -+ grub_uint32_t evt_cc = (grub_xhci_read32(&etrb->status) >> 24) & 0xff; -+ -+ switch (evt_type) -+ { -+ case ER_TRANSFER: -+ case ER_COMMAND_COMPLETE: -+ { -+ struct grub_xhci_trb *rtrb = (void*)grub_xhci_read32(&etrb->ptr_low); -+ struct grub_xhci_ring *ring = XHCI_RING(rtrb); -+ volatile struct grub_xhci_trb *evt = &ring->evt; -+ grub_uint32_t eidx = rtrb - ring->ring + 1; -+ grub_dprintf("xhci", "%s: ring %p [trb %p, evt %p, type %d, eidx %d, cc %d]\n", -+ __func__, ring, rtrb, evt, evt_type, eidx, evt_cc); -+ *evt = *etrb; -+ grub_xhci_write32(&ring->eidx, eidx); -+ break; -+ } -+ case ER_PORT_STATUS_CHANGE: -+ { -+ /* Nothing to do here. grub_xhci_detect_dev will handle it */ -+ break; -+ } -+ default: -+ { -+ grub_dprintf("xhci", "%s: unknown event, type %d, cc %d\n", -+ __func__, evt_type, evt_cc); -+ break; -+ } -+ } -+ -+ /* move ring index, notify xhci */ -+ nidx++; -+ if (nidx == GRUB_XHCI_RING_ITEMS) -+ { -+ nidx = 0; -+ cs = cs ? 0 : 1; -+ grub_xhci_write32(&evts->cs, cs); -+ } -+ grub_xhci_write32(&evts->nidx, nidx); -+ volatile struct grub_xhci_ir *ir = x->ir; -+ grub_uint32_t erdp = (grub_uint32_t)(evts->ring + nidx); -+ grub_xhci_write32(&ir->erdp_low, erdp); -+ grub_xhci_write32(&ir->erdp_high, 0); -+ } -+} -+ -+/**************************************************************** -+ * TRB handling -+ ****************************************************************/ -+ -+/* Signal the hardware to process events on a TRB ring */ -+static void xhci_doorbell(struct grub_xhci *x, grub_uint32_t slotid, grub_uint32_t value) -+{ -+ xhci_check_status(x); -+ grub_dprintf("xhci", "%s: slotid %d, epid %d\n", __func__, slotid, value); -+ grub_xhci_write32(&x->db[slotid].doorbell, value); -+} -+ -+/* Check if a ring has any pending TRBs */ -+static int xhci_ring_busy(volatile struct grub_xhci_ring *ring) -+{ -+ grub_uint32_t eidx = grub_xhci_read32(&ring->eidx); -+ grub_uint32_t nidx = grub_xhci_read32(&ring->nidx); -+ -+ return (eidx != nidx); -+} -+ -+/* Returns free space in ring */ -+static int xhci_ring_free_space(volatile struct grub_xhci_ring *ring) -+{ -+ grub_uint32_t eidx = grub_xhci_read32(&ring->eidx); -+ grub_uint32_t nidx = grub_xhci_read32(&ring->nidx); -+ -+ /* nidx is never 0, so reduce ring buffer size by one */ -+ return (eidx > nidx) ? eidx-nidx -+ : (ARRAY_SIZE(ring->ring) - 1) - nidx + eidx; -+} -+ -+/* Check if a ring is full */ -+static int xhci_ring_full(volatile struct grub_xhci_ring *ring) -+{ -+ /* Might need to insert one link TRB */ -+ return xhci_ring_free_space(ring) <= 1; -+} -+ -+/* Check if a ring is almost full */ -+static int xhci_ring_almost_full(volatile struct grub_xhci_ring *ring) -+{ -+ /* Might need to insert one link TRB */ -+ return xhci_ring_free_space(ring) <= 2; -+} -+ -+/* Wait for a ring to empty (all TRBs processed by hardware) */ -+static int xhci_event_wait(struct grub_xhci *x, -+ volatile struct grub_xhci_ring *ring, -+ grub_uint32_t timeout) -+{ -+ grub_uint32_t end = grub_get_time_ms () + timeout; -+ -+ for (;;) -+ { -+ xhci_check_status(x); -+ xhci_process_events(x); -+ if (!xhci_ring_busy(ring)) -+ { -+ grub_uint32_t status = ring->evt.status; -+ return (status >> 24) & 0xff; -+ } -+ if (grub_get_time_ms () > end) -+ { -+ xhci_check_status(x); -+ grub_dprintf("xhci", "%s: Timeout waiting for event\n", __func__); -+ return -1; -+ } -+ } -+} -+ -+/* Add a TRB to the given ring, either regular or inline */ -+static void xhci_trb_fill(volatile struct grub_xhci_ring *ring, -+ grub_uint64_t ptr, grub_uint32_t xferlen, -+ grub_uint32_t flags) -+{ -+ volatile struct grub_xhci_trb *dst = &ring->ring[ring->nidx]; -+ dst->ptr_low = ptr & 0xffffffff; -+ dst->ptr_high = ptr >> 32; -+ dst->status = xferlen; -+ dst->control = flags | (ring->cs ? TRB_C : 0); -+ -+ grub_arch_sync_dma_caches(dst, sizeof(ring->ring[0])); -+} -+ -+/* -+ * Queue a TRB onto a ring. -+ * -+ * The caller must pass a pointer to the data in physical address-space or the -+ * data itself (but no more than 8 bytes) in data_or_addr. Inline data must have -+ * the flag TRB_TR_IDT set. -+ */ -+static void xhci_trb_queue(volatile struct grub_xhci_ring *ring, -+ grub_uint64_t data_or_addr, -+ grub_uint32_t xferlen, grub_uint32_t flags) -+{ -+ grub_dprintf("xhci", "%s: ring %p data %llx len %d flags 0x%x remain 0x%x\n", __func__, -+ ring, data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17); -+ -+ if (xhci_ring_full(ring)) -+ { -+ grub_dprintf("xhci", "%s: ERROR: ring %p is full, discarding TRB\n", -+ __func__, ring); -+ return; -+ } -+ -+ if (ring->nidx >= ARRAY_SIZE(ring->ring) - 1) -+ { -+ /* Reset to command buffer pointer to the first element */ -+ xhci_trb_fill(ring, (grub_addr_t)ring->ring, 0, (TR_LINK << 10) | TRB_LK_TC); -+ ring->nidx = 0; -+ ring->cs ^= 1; -+ grub_dprintf("xhci", "%s: ring %p [linked]\n", __func__, ring); -+ } -+ -+ xhci_trb_fill(ring, data_or_addr, xferlen, flags); -+ ring->nidx++; -+ grub_dprintf("xhci", "%s: ring %p [nidx %d, len %d]\n", -+ __func__, ring, ring->nidx, xferlen); -+} -+ -+/* -+ * Queue a TRB onto a ring and flush it if necessary. -+ * -+ * The caller must pass a pointer to the data in physical address-space or the -+ * data itself (but no more than 8 bytes) in data_or_addr. Inline data must have -+ * the flag TRB_TR_IDT set. -+ */ -+static int xhci_trb_queue_and_flush(struct grub_xhci *x, -+ grub_uint32_t slotid, -+ grub_uint32_t epid, -+ volatile struct grub_xhci_ring *ring, -+ grub_uint64_t data_or_addr, -+ grub_uint32_t xferlen, grub_uint32_t flags) -+{ -+ grub_uint8_t submit = 0; -+ if (xhci_ring_almost_full(ring)) -+ { -+ grub_dprintf("xhci", "%s: almost full e %d n %d\n", __func__, ring->eidx, ring->nidx); -+ flags |= TRB_TR_IOC; -+ submit = 1; -+ } -+ /* Note: xhci_trb_queue might queue on or two elements, if the end of the TRB -+ * has been reached. The caller must account for that when filling the TRB. */ -+ xhci_trb_queue(ring, data_or_addr, xferlen, flags); -+ /* Submit if less no free slot is remaining, we might need an additional -+ * one on the next call to this function. */ -+ if (submit) -+ { -+ xhci_doorbell(x, slotid, epid); -+ int rc = xhci_event_wait(x, ring, 1000); -+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc); -+ return rc; -+ } -+ return 0; -+} -+ -+/**************************************************************** -+ * xHCI command functions -+ ****************************************************************/ -+ -+/* Submit a command to the xHCI command TRB */ -+static int xhci_cmd_submit(struct grub_xhci *x, -+ struct grub_pci_dma_chunk *inctx_dma, -+ grub_uint32_t flags) -+{ -+ volatile struct grub_xhci_inctx *inctx; -+ /* Don't submit if halted, it will fail */ -+ if (xhci_is_halted(x)) -+ return -1; -+ -+ if (inctx_dma) -+ { -+ grub_xhci_inctx_sync_dma_caches(x, inctx_dma); -+ -+ inctx = grub_dma_get_virt(inctx_dma); -+ -+ struct grub_xhci_slotctx *slot = (void*)&inctx[1 << x->flag64]; -+ grub_uint32_t port = ((slot->ctx[1] >> 16) & 0xff) - 1; -+ grub_uint32_t portsc = grub_xhci_port_read(x, port); -+ if (!(portsc & GRUB_XHCI_PORTSC_CCS)) -+ { -+ grub_dprintf("xhci", "%s: root port %d no longer connected\n", -+ __func__, port); -+ return -1; -+ } -+ xhci_trb_queue(x->cmds, grub_dma_get_phys(inctx_dma), 0, flags); -+ } -+ else -+ { -+ xhci_trb_queue(x->cmds, 0, 0, flags); -+ } -+ -+ xhci_doorbell(x, 0, 0); -+ int rc = xhci_event_wait(x, x->cmds, 1000); -+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc); -+ -+ return rc; -+} -+ -+static int xhci_cmd_enable_slot(struct grub_xhci *x) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (CR_ENABLE_SLOT << 10); -+ -+ grub_dprintf("xhci", "%s:\n", __func__); -+ int cc = xhci_cmd_submit(x, NULL, flags); -+ if (cc != CC_SUCCESS) -+ return -1; -+ grub_dprintf("xhci", "%s: %p\n", __func__, &x->cmds->evt.control); -+ grub_dprintf("xhci", "%s: %x\n", __func__, grub_xhci_read32(&x->cmds->evt.control)); -+ -+ return (grub_xhci_read32(&x->cmds->evt.control) >> 24) & 0xff; -+} -+ -+static int xhci_cmd_disable_slot(struct grub_xhci *x, grub_uint32_t slotid) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (CR_DISABLE_SLOT << 10); -+ flags |= (slotid << 24); -+ -+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid); -+ return xhci_cmd_submit(x, NULL, flags); -+} -+ -+static int xhci_cmd_stop_endpoint(struct grub_xhci *x, grub_uint32_t slotid -+ , grub_uint32_t epid -+ , grub_uint32_t suspend) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (CR_STOP_ENDPOINT << 10); -+ flags |= (epid << 16); -+ flags |= (suspend << 23) ; -+ flags |= (slotid << 24); -+ -+ return xhci_cmd_submit(x, NULL, flags); -+} -+ -+static int xhci_cmd_reset_endpoint(struct grub_xhci *x, grub_uint32_t slotid -+ , grub_uint32_t epid -+ , grub_uint32_t preserve) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (preserve << 9); -+ flags |= (CR_RESET_ENDPOINT << 10); -+ flags |= (epid << 16); -+ flags |= (slotid << 24); -+ -+ return xhci_cmd_submit(x, NULL, flags); -+} -+ -+static int xhci_cmd_set_dequeue_pointer(struct grub_xhci *x, grub_uint32_t slotid -+ , grub_uint32_t epid -+ , grub_addr_t tr_deque_pointer) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (CR_SET_TR_DEQUEUE << 10); -+ flags |= (epid << 16); -+ flags |= (slotid << 24); -+ -+ xhci_trb_queue(x->cmds, tr_deque_pointer, 0, flags); -+ -+ xhci_doorbell(x, 0, 0); -+ int rc = xhci_event_wait(x, x->cmds, 1000); -+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc); -+ -+ return rc; -+} -+ -+static int xhci_cmd_address_device(struct grub_xhci *x, grub_uint32_t slotid, -+ struct grub_pci_dma_chunk *inctx_dma) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (CR_ADDRESS_DEVICE << 10); -+ flags |= (slotid << 24); -+ -+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid); -+ return xhci_cmd_submit(x, inctx_dma, flags); -+} -+ -+static int xhci_cmd_configure_endpoint(struct grub_xhci *x, grub_uint32_t slotid, -+ struct grub_pci_dma_chunk *inctx_dma) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (CR_CONFIGURE_ENDPOINT << 10); -+ flags |= (slotid << 24); -+ -+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid); -+ return xhci_cmd_submit(x, inctx_dma, flags); -+} -+ -+static int xhci_cmd_evaluate_context(struct grub_xhci *x, grub_uint32_t slotid, -+ struct grub_pci_dma_chunk *inctx_dma) -+{ -+ grub_uint32_t flags = 0; -+ flags |= (CR_EVALUATE_CONTEXT << 10); -+ flags |= (slotid << 24); -+ -+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid); -+ return xhci_cmd_submit(x, inctx_dma, flags); -+} -+ -+/**************************************************************** -+ * xHCI host controller initialization -+ ****************************************************************/ -+ -+static grub_usb_err_t -+grub_xhci_reset (struct grub_xhci *x) -+{ -+ grub_uint32_t reg; -+ grub_uint32_t end; -+ -+ reg = grub_xhci_read32(&x->op->usbcmd); -+ if (reg & GRUB_XHCI_CMD_RS) -+ { -+ reg &= ~GRUB_XHCI_CMD_RS; -+ grub_xhci_write32(&x->op->usbcmd, reg); -+ -+ end = grub_get_time_ms () + 32; -+ while (grub_xhci_read32(&x->op->usbcmd) & GRUB_XHCI_STS_HCH) -+ { -+ if (grub_get_time_ms () > end) -+ return GRUB_USB_ERR_TIMEOUT; -+ -+ grub_millisleep(1); -+ } -+ } -+ -+ grub_dprintf("xhci", "grub_xhci_reset: resetting HC\n"); -+ grub_xhci_write32(&x->op->usbcmd, GRUB_XHCI_CMD_HCRST); -+ -+ /* Wait for device to complete reset and be enabled */ -+ end = grub_get_time_ms () + 100; -+ while (grub_xhci_read32(&x->op->usbcmd) & GRUB_XHCI_CMD_HCRST) -+ { -+ if (grub_get_time_ms () > end) -+ return GRUB_USB_ERR_TIMEOUT; -+ -+ grub_millisleep(1); -+ } -+ -+ /* Wait for device to complete reset and be enabled */ -+ end = grub_get_time_ms () + 100; -+ while (grub_xhci_read32(&x->op->usbsts) & GRUB_XHCI_STS_CNR) -+ { -+ if (grub_get_time_ms () > end) -+ return GRUB_USB_ERR_TIMEOUT; -+ -+ grub_millisleep(1); -+ } -+ -+ grub_xhci_write32(&x->op->config, x->slots); -+ grub_xhci_write32(&x->op->dcbaap_low, grub_dma_get_phys(x->devs_dma)); -+ grub_xhci_write32(&x->op->dcbaap_high, 0); -+ grub_xhci_write32(&x->op->crcr_low, grub_dma_get_phys(x->cmds_dma)| 1); -+ grub_xhci_write32(&x->op->crcr_high, 0); -+ x->cmds->cs = 1; -+ -+ grub_arch_sync_dma_caches(x->cmds, sizeof(*x->cmds)); -+ -+ x->eseg->ptr_low = grub_dma_get_phys(x->evts_dma); -+ x->eseg->ptr_high = 0; -+ x->eseg->size = GRUB_XHCI_RING_ITEMS; -+ -+ grub_arch_sync_dma_caches(x->eseg, sizeof(*x->eseg)); -+ -+ grub_xhci_write32(&x->ir->erstsz, 1); -+ grub_xhci_write32(&x->ir->erdp_low, grub_dma_get_phys(x->evts_dma)); -+ grub_xhci_write32(&x->ir->erdp_high, 0); -+ grub_xhci_write32(&x->ir->erstba_low, grub_dma_get_phys(x->eseg_dma)); -+ grub_xhci_write32(&x->ir->erstba_high, 0); -+ x->evts->cs = 1; -+ -+ grub_arch_sync_dma_caches(x->evts, sizeof(*x->eseg)); -+ -+ xhci_check_status(x); -+ -+ grub_dprintf ("xhci", "XHCI OP COMMAND: %08x\n", -+ grub_xhci_read32 (&x->op->usbcmd)); -+ grub_dprintf ("xhci", "XHCI OP STATUS: %08x\n", -+ grub_xhci_read32 (&x->op->usbsts)); -+ grub_dprintf ("xhci", "XHCI OP PAGESIZE: %08x\n", -+ grub_xhci_read32 (&x->op->pagesize)); -+ grub_dprintf ("xhci", "XHCI OP DNCTRL: %08x\n", -+ grub_xhci_read32 (&x->op->dnctl)); -+ grub_dprintf ("xhci", "XHCI OP CRCR_LOW: %08x\n", -+ grub_xhci_read32 (&x->op->crcr_low)); -+ grub_dprintf ("xhci", "XHCI OP CRCR_HIGH: %08x\n", -+ grub_xhci_read32 (&x->op->crcr_high)); -+ grub_dprintf ("xhci", "XHCI OP DCBAAP_LOW: %08x\n", -+ grub_xhci_read32 (&x->op->dcbaap_low)); -+ grub_dprintf ("xhci", "XHCI OP DCBAAP_HIGH: %08x\n", -+ grub_xhci_read32 (&x->op->dcbaap_high)); -+ grub_dprintf ("xhci", "XHCI OP CONFIG: %08x\n", -+ grub_xhci_read32 (&x->op->config)); -+ grub_dprintf ("xhci", "XHCI IR ERSTSZ: %08x\n", -+ grub_xhci_read32 (&x->ir->erstsz)); -+ grub_dprintf ("xhci", "XHCI IR ERDP: %08x\n", -+ grub_xhci_read32 (&x->ir->erdp_low)); -+ grub_dprintf ("xhci", "XHCI IR ERSTBA: %08x\n", -+ grub_xhci_read32 (&x->ir->erstba_low)); -+ -+ xhci_check_status(x); -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+static grub_usb_err_t -+grub_xhci_request_legacy_handoff(volatile struct grub_xhci_xcap *xcap) -+{ -+ grub_uint32_t end; -+ -+ end = grub_get_time_ms () + 10; -+ for (;;) -+ { -+ grub_uint32_t cap = grub_xhci_read32(&xcap->cap); -+ if (cap & (1 << 16)) -+ grub_xhci_write32(&xcap->cap, cap | (1 << 24)); -+ else -+ break; -+ -+ if (grub_get_time_ms () > end) -+ { -+ grub_dprintf ("xhci","ERROR: %s TIMEOUT\n", __func__); -+ return GRUB_USB_ERR_TIMEOUT; -+ } -+ grub_millisleep(1); -+ } -+ return GRUB_USB_ERR_NONE; -+} -+ -+static void -+grub_xhci_fill_default_speed_mapping(struct grub_xhci_psids *ids) -+{ -+ /* Chapter 7.2.2.1.1 "Default USB Speed ID Mapping" */ -+ ids->psids[0].id = 1; -+ ids->psids[0].psie = 2; -+ ids->psids[0].psim = 12; -+ ids->psids[1].id = 2; -+ ids->psids[1].psie = 1; -+ ids->psids[1].psim = 1500; -+ ids->psids[2].id = 3; -+ ids->psids[2].psie = 2; -+ ids->psids[2].psim = 480; -+ ids->psids[3].id = 4; -+ ids->psids[3].psie = 3; -+ ids->psids[3].psim = 5; -+ ids->psids[4].id = 5; -+ ids->psids[4].psie = 3; -+ ids->psids[4].psim = 10; -+ ids->psids[5].id = 6; -+ ids->psids[5].psie = 3; -+ ids->psids[5].psim = 10; -+ ids->psids[6].id = 7; -+ ids->psids[6].psie = 3; -+ ids->psids[6].psim = 20; -+} -+ -+static void -+grub_xhci_calc_speed_mapping(struct grub_xhci_psids *ids) -+{ -+ const grub_uint64_t mult[4] = {1ULL, 1000ULL, 1000000ULL, 1000000000ULL}; -+ -+ for (grub_uint8_t i = 0; i < 16; i++) -+ { -+ if (ids->psids[i].id == 0) -+ continue; -+ ids->psids[i].bitrate = mult[ids->psids[i].psie & 3] * (grub_uint64_t)ids->psids[i].psim; -+ if (ids->psids[i].bitrate < 12000000ULL) -+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_LOW; -+ else if (ids->psids[i].bitrate < 480000000ULL) -+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_FULL; -+ else if (ids->psids[i].bitrate > 1200000000ULL) -+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_SUPER; -+ else -+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_HIGH; -+ } -+} -+ -+ -+/* PCI iteration function... */ -+void -+grub_xhci_init_device (volatile void *regs) -+{ -+ struct grub_xhci *x; -+ grub_uint32_t hcs1, hcc, reg; -+ -+ /* Allocate memory for the controller and fill basic values. */ -+ x = grub_zalloc (sizeof (*x)); -+ if (!x) -+ { -+ grub_dprintf("xhci", "Failed to allocate memory\n"); -+ return; -+ } -+ x->caps = (volatile struct grub_xhci_caps *) regs; -+ x->op = (volatile struct grub_xhci_op *) (((grub_uint8_t *)regs) + -+ grub_xhci_read8(&x->caps->caplength)); -+ x->pr = (volatile struct grub_xhci_pr *) (((grub_uint8_t *)x->op) + -+ GRUB_XHCI_PR_OFFSET); -+ x->db = (volatile struct grub_xhci_db *) (((grub_uint8_t *)regs) + -+ grub_xhci_read32(&x->caps->dboff)); -+ x->ir = (volatile struct grub_xhci_ir *) (((grub_uint8_t *)regs) + -+ grub_xhci_read32(&x->caps->rtsoff) + GRUB_XHCI_IR_OFFSET); -+ -+ grub_dprintf ("xhci", "XHCI init: CAPLENGTH: 0x%02x\n", -+ grub_xhci_read8 (&x->caps->caplength)); -+ grub_dprintf ("xhci", "XHCI init: HCIVERSION: 0x%04x\n", -+ grub_xhci_read16 (&x->caps->hciversion)); -+ grub_dprintf ("xhci", "XHCI init: HCSPARAMS1: 0x%08x\n", -+ grub_xhci_read32 (&x->caps->hcsparams1)); -+ grub_dprintf ("xhci", "XHCI init: HCSPARAMS2: 0x%08x\n", -+ grub_xhci_read32 (&x->caps->hcsparams2)); -+ grub_dprintf ("xhci", "XHCI init: HCSPARAMS3: 0x%08x\n", -+ grub_xhci_read32 (&x->caps->hcsparams3)); -+ grub_dprintf ("xhci", "XHCI init: HCCPARAMS: 0x%08x\n", -+ grub_xhci_read32 (&x->caps->hcsparams3)); -+ grub_dprintf ("xhci", "XHCI init: DBOFF: 0x%08x\n", -+ grub_xhci_read32 (&x->caps->dboff)); -+ grub_dprintf ("xhci", "XHCI init: RTOFF: 0x%08x\n", -+ grub_xhci_read32 (&x->caps->rtsoff)); -+ -+ hcs1 = grub_xhci_read32(&x->caps->hcsparams1); -+ hcc = grub_xhci_read32(&x->caps->hccparams); -+ x->ports = (grub_uint32_t) ((hcs1 >> 24) & 0xff); -+ x->slots = (grub_uint32_t) (hcs1 & 0xff); -+ x->xcap = (grub_uint32_t) ((hcc >> 16) & 0xffff) * sizeof(grub_uint32_t); -+ x->flag64 = (grub_uint8_t) ((hcc & 0x04) ? 1 : 0); -+ grub_dprintf("xhci", "XHCI init: %d ports, %d slots, %d byte contexts\n" -+ , x->ports, x->slots, x->flag64 ? 64 : 32); -+ -+ x->psids = grub_zalloc (sizeof (struct grub_xhci_psids) * x->ports); -+ if (x->xcap) -+ { -+ grub_uint32_t off; -+ volatile grub_uint8_t *addr = (grub_uint8_t *) x->caps + x->xcap; -+ do -+ { -+ volatile struct grub_xhci_xcap *xcap = (void *)addr; -+ grub_uint32_t ports, name, cap = grub_xhci_read32(&xcap->cap); -+ switch (cap & 0xff) { -+ case XHCI_CAP_LEGACY_SUPPORT: -+ { -+ if (grub_xhci_request_legacy_handoff(xcap) != GRUB_USB_ERR_NONE) -+ { -+ grub_dprintf("xhci", "XHCI init: Failed to get xHCI ownership\n"); -+ goto fail; -+ } -+ break; -+ } -+ case XHCI_CAP_SUPPORTED_PROTOCOL: -+ { -+ name = grub_xhci_read32(&xcap->data[0]); -+ ports = grub_xhci_read32(&xcap->data[1]); -+ const grub_uint8_t major = (cap >> 24) & 0xff; -+ const grub_uint8_t minor = (cap >> 16) & 0xff; -+ const grub_uint8_t psic = (ports >> 28) & 0xf; -+ const grub_uint8_t count = (ports >> 8) & 0xff; -+ const grub_uint8_t start = (ports >> 0) & 0xff; -+ grub_dprintf("xhci", "XHCI init: protocol %c%c%c%c %x.%02x" -+ ", %d ports (offset %d), def %x, psic %d\n" -+ , (name >> 0) & 0xff -+ , (name >> 8) & 0xff -+ , (name >> 16) & 0xff -+ , (name >> 24) & 0xff -+ , major, minor -+ , count, start -+ , ports >> 16 -+ , psic); -+ if (name == 0x20425355 /* "USB " */) -+ { -+ if (major == 2) -+ { -+ x->usb2.start = start; -+ x->usb2.count = count; -+ } -+ else if (major == 3) -+ { -+ x->usb3.start = start; -+ x->usb3.count = count; -+ } -+ -+ for (grub_uint32_t p = start - 1; p < start + count - 1UL; p++) -+ { -+ x->psids[p].major = major; -+ x->psids[p].minor = minor; -+ grub_xhci_fill_default_speed_mapping(&x->psids[p]); -+ for (grub_uint8_t i = 0; i < psic; i++) -+ { -+ grub_uint32_t psid = grub_xhci_read32(&xcap->data[3 + i]); -+ x->psids[p].psids[i].id = (psid >> 0) & 0xf; -+ x->psids[p].psids[i].psie = (psid >> 4) & 0x3; -+ x->psids[p].psids[i].psim = (psid >> 16) & 0xfffff; -+ } -+ grub_xhci_calc_speed_mapping(&x->psids[p]); -+ } -+ } -+ -+ break; -+ } -+ default: -+ { -+ grub_dprintf("xhci", "XHCI extcap 0x%x @ %p\n", cap & 0xff, addr); -+ break; -+ } -+ } -+ off = (cap >> 8) & 0xff; -+ addr += off << 2; -+ } -+ while (off > 0); -+ } -+ -+ x->pagesize = xhci_get_pagesize(x); -+ grub_dprintf("xhci", "XHCI init: Minimum supported page size 0x%x\n", -+ x->pagesize); -+ -+ /* Chapter 6.1 Device Context Base Address Array */ -+ x->devs_dma = xhci_memalign_dma32(ALIGN_DCBAA, -+ sizeof(*x->devs) * (x->slots + 1), -+ x->pagesize); -+ if (!x->devs_dma) -+ goto fail; -+ x->devs = grub_dma_get_virt(x->devs_dma); -+ grub_memset((void *)x->devs, 0, sizeof(*x->devs) * (x->slots + 1)); -+ grub_arch_sync_dma_caches(x->devs, sizeof(*x->devs) * (x->slots + 1)); -+ grub_dprintf ("xhci", "XHCI init: device memory %p (%x)\n", -+ grub_dma_get_virt(x->devs_dma), -+ grub_dma_get_phys(x->devs_dma)); -+ -+ /* Chapter 6.5 Event Ring Segment Table */ -+ x->eseg_dma = xhci_memalign_dma32(ALIGN_EVT_RING_TABLE, sizeof(*x->eseg), 0); -+ if (!x->eseg_dma) -+ goto fail; -+ x->eseg = grub_dma_get_virt(x->eseg_dma); -+ grub_memset((void *)x->eseg, 0, sizeof(*x->eseg)); -+ grub_arch_sync_dma_caches(x->eseg, sizeof(*x->eseg)); -+ grub_dprintf ("xhci", "XHCI init: event ring table memory %p (%x)\n", -+ grub_dma_get_virt(x->eseg_dma), -+ grub_dma_get_phys(x->eseg_dma)); -+ -+ x->cmds_dma = xhci_memalign_dma32(ALIGN_CMD_RING_SEG, sizeof(*x->cmds), -+ BOUNDARY_RING); -+ if (!x->cmds_dma) -+ goto fail; -+ x->cmds = grub_dma_get_virt(x->cmds_dma); -+ grub_memset((void *)x->cmds, 0, sizeof(*x->cmds)); -+ grub_arch_sync_dma_caches(x->cmds, sizeof(*x->cmds)); -+ grub_dprintf ("xhci", "XHCI init: command ring memory %p (%x)\n", -+ grub_dma_get_virt(x->cmds_dma), -+ grub_dma_get_phys(x->cmds_dma)); -+ -+ x->evts_dma = xhci_memalign_dma32(ALIGN_EVT_RING_SEG, sizeof(*x->evts), -+ BOUNDARY_RING); -+ if (!x->evts_dma) -+ goto fail; -+ x->evts = grub_dma_get_virt(x->evts_dma); -+ grub_memset((void *)x->evts, 0, sizeof(*x->evts)); -+ grub_arch_sync_dma_caches(x->evts, sizeof(*x->evts)); -+ grub_dprintf ("xhci", "XHCI init: event ring memory %p (%x)\n", -+ grub_dma_get_virt(x->evts_dma), -+ grub_dma_get_phys(x->evts_dma)); -+ -+ /* Chapter 4.20 Scratchpad Buffers */ -+ reg = grub_xhci_read32(&x->caps->hcsparams2); -+ x->spb = (reg >> 21 & 0x1f) << 5 | reg >> 27; -+ if (x->spb) -+ { -+ volatile grub_uint64_t *spba; -+ grub_dprintf("xhci", "XHCI init: set up %d scratch pad buffers\n", -+ x->spb); -+ x->spba_dma = xhci_memalign_dma32(ALIGN_SPBA, sizeof(*spba) * x->spb, -+ x->pagesize); -+ if (!x->spba_dma) -+ goto fail; -+ -+ x->spad_dma = xhci_memalign_dma32(x->pagesize, x->pagesize * x->spb, -+ x->pagesize); -+ if (!x->spad_dma) -+ { -+ grub_dma_free(x->spba_dma); -+ goto fail; -+ } -+ -+ spba = grub_dma_get_virt(x->spba_dma); -+ for (grub_uint32_t i = 0; i < x->spb; i++) -+ spba[i] = (grub_addr_t)grub_dma_get_phys(x->spad_dma) + (i * x->pagesize); -+ grub_arch_sync_dma_caches(x->spba_dma, sizeof(*spba) * x->spb); -+ -+ x->devs[0].ptr_low = grub_dma_get_phys(x->spba_dma); -+ x->devs[0].ptr_high = 0; -+ grub_arch_sync_dma_caches(x->devs_dma, sizeof(x->devs[0])); -+ grub_dprintf ("xhci", "XHCI init: Allocated %d scratch buffers of size 0x%x\n", -+ x->spb, x->pagesize); -+ } -+ -+ grub_xhci_reset(x); -+ -+ /* Set the running bit */ -+ reg = grub_xhci_read32 (&x->op->usbcmd); -+ reg |= GRUB_XHCI_CMD_RS; -+ grub_xhci_write32 (&x->op->usbcmd, reg); -+ -+ -+ /* Link to xhci now that initialisation is successful. */ -+ x->next = xhci; -+ xhci = x; -+ -+ return; -+ -+fail: -+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: FAILED!\n"); -+ if (x) -+ { -+ if (x->devs_dma) -+ grub_dma_free (x->devs_dma); -+ if (x->eseg_dma) -+ grub_dma_free (x->eseg_dma); -+ if (x->cmds_dma) -+ grub_dma_free (x->cmds_dma); -+ if (x->evts_dma) -+ grub_dma_free (x->evts_dma); -+ if (x->spad_dma) -+ grub_dma_free (x->spad_dma); -+ if (x->spba_dma) -+ grub_dma_free (x->spba_dma); -+ } -+ grub_free (x); -+ -+ return; -+} -+ -+static int -+grub_xhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) -+{ -+ struct grub_xhci *x; -+ struct grub_usb_controller dev; -+ -+ for (x = xhci; x; x = x->next) -+ { -+ dev.data = x; -+ if (hook (&dev, hook_data)) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/**************************************************************** -+ * xHCI maintainance functions -+ ****************************************************************/ -+ -+static grub_usb_err_t -+grub_xhci_update_hub_portcount (struct grub_xhci *x, -+ grub_usb_transfer_t transfer, -+ grub_uint32_t slotid) -+{ -+ struct grub_pci_dma_chunk *in_dma; -+ volatile struct grub_xhci_slotctx *hdslot; -+ grub_uint32_t epid = 0; -+ -+ if (!transfer || !transfer->dev || !transfer->dev->nports) -+ return GRUB_USB_ERR_NONE; -+ -+ hdslot = grub_dma_phys2virt(x->devs[slotid].ptr_low, x->devs_dma); -+ if ((hdslot->ctx[3] >> 27) == 3) -+ /* Already configured */ -+ return 0; -+ -+ grub_dprintf("xhci", "%s: updating hub config to %d ports\n", __func__, -+ transfer->dev->nports); -+ -+ xhci_check_status(x); -+ -+ /* Allocate input context and initialize endpoint info. */ -+ in_dma = grub_xhci_alloc_inctx(x, epid, transfer->dev); -+ if (!in_dma) -+ return GRUB_USB_ERR_INTERNAL; -+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(in_dma); -+ -+ in->add = (1 << epid); -+ -+ struct grub_xhci_epctx *ep = (void*)&in[(epid+1) << x->flag64]; -+ ep->ctx[0] |= 1 << 26; -+ ep->ctx[1] |= transfer->dev->nports << 24; -+ -+ int cc = xhci_cmd_configure_endpoint(x, slotid, in_dma); -+ grub_dma_free(in_dma); -+ -+ if (cc != CC_SUCCESS) -+ { -+ grub_dprintf("xhci", "%s: reconf ctl endpoint: failed (cc %d)\n", -+ __func__, cc); -+ return GRUB_USB_ERR_BADDEVICE; -+ } -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+static grub_usb_err_t -+grub_xhci_update_max_paket_size (struct grub_xhci *x, -+ grub_usb_transfer_t transfer, -+ grub_uint32_t slotid, -+ grub_uint32_t max_packet) -+{ -+ struct grub_pci_dma_chunk *in_dma; -+ grub_uint32_t epid = 1; -+ -+ if (!transfer || !transfer->dev || !max_packet) -+ return GRUB_USB_ERR_NONE; -+ -+ grub_dprintf("xhci", "%s: updating max packet size to 0x%x\n", __func__, -+ max_packet); -+ -+ xhci_check_status(x); -+ -+ /* Allocate input context and initialize endpoint info. */ -+ in_dma = grub_xhci_alloc_inctx(x, epid, transfer->dev); -+ if (!in_dma) -+ return GRUB_USB_ERR_INTERNAL; -+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(in_dma); -+ in->add = (1 << epid); -+ -+ struct grub_xhci_epctx *ep = (void*)&in[(epid+1) << x->flag64]; -+ ep->ctx[1] |= max_packet << 16; -+ -+ int cc = xhci_cmd_evaluate_context(x, slotid, in_dma); -+ grub_dma_free(in_dma); -+ -+ if (cc != CC_SUCCESS) -+ { -+ grub_dprintf("xhci", "%s: reconf ctl endpoint: failed (cc %d)\n", -+ __func__, cc); -+ return GRUB_USB_ERR_BADDEVICE; -+ } -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+/**************************************************************** -+ * xHCI endpoint enablement functions -+ ****************************************************************/ -+ -+static grub_usb_err_t -+grub_xhci_prepare_endpoint (struct grub_xhci *x, -+ struct grub_usb_device *dev, -+ grub_uint8_t endpoint, -+ grub_transfer_type_t dir, -+ grub_transaction_type_t type, -+ grub_uint32_t maxpaket, -+ struct grub_xhci_priv *priv) -+{ -+ grub_uint32_t epid; -+ struct grub_pci_dma_chunk *reqs_dma; -+ struct grub_pci_dma_chunk *in_dma; -+ volatile struct grub_xhci_ring *reqs; -+ volatile struct grub_xhci_slotctx *slotctx; -+ -+ if (!x || !priv) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ xhci_check_status(x); -+ -+ if (endpoint == 0) -+ { -+ epid = 1; -+ } -+ else -+ { -+ epid = (endpoint & 0x0f) * 2; -+ epid += (dir == GRUB_USB_TRANSFER_TYPE_IN) ? 1 : 0; -+ } -+ grub_dprintf("xhci", "%s: epid %d\n", __func__, epid); -+ -+ /* Test if already prepared */ -+ if (priv->slotid > 0 && priv->enpoint_trbs[epid] != NULL) -+ return GRUB_USB_ERR_NONE; -+ -+ /* Allocate DMA buffer as endpoint cmd TRB */ -+ reqs_dma = xhci_memalign_dma32(ALIGN_TRB, sizeof(*reqs), -+ BOUNDARY_RING); -+ if (!reqs_dma) -+ return GRUB_USB_ERR_INTERNAL; -+ reqs = grub_dma_get_virt(reqs_dma); -+ grub_memset((void *)reqs, 0, sizeof(*reqs)); -+ reqs->cs = 1; -+ -+ grub_arch_sync_dma_caches(reqs, sizeof(*reqs)); -+ -+ /* Allocate input context and initialize endpoint info. */ -+ in_dma = grub_xhci_alloc_inctx(x, epid, dev); -+ if (!in_dma) -+ { -+ grub_dma_free(reqs_dma); -+ return GRUB_USB_ERR_INTERNAL; -+ } -+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(in_dma); -+ in->add = 0x01 | (1 << epid); -+ -+ struct grub_xhci_epctx *ep = (void*)&in[(epid+1) << x->flag64]; -+ switch (type) -+ { -+ case GRUB_USB_TRANSACTION_TYPE_CONTROL: -+ ep->ctx[1] |= 0 << 3; -+ break; -+ case GRUB_USB_TRANSACTION_TYPE_BULK: -+ ep->ctx[1] |= 2 << 3; -+ break; -+ } -+ if (dir == GRUB_USB_TRANSFER_TYPE_IN -+ || type== GRUB_USB_TRANSACTION_TYPE_CONTROL) -+ ep->ctx[1] |= 1 << 5; -+ ep->ctx[1] |= maxpaket << 16; -+ ep->deq_low = grub_dma_get_phys(reqs_dma); -+ ep->deq_low |= 1; /* dcs */ -+ ep->length = maxpaket; -+ -+ grub_dprintf("xhci", "%s: ring %p, epid %d, max %d\n", __func__, -+ reqs, epid, maxpaket); -+ if (epid == 1 || priv->slotid == 0) { -+ /* Enable slot. */ -+ int slotid = xhci_cmd_enable_slot(x); -+ if (slotid < 0) -+ { -+ grub_dprintf("xhci", "%s: enable slot: failed\n", __func__); -+ grub_dma_free(reqs_dma); -+ grub_dma_free(in_dma); -+ return GRUB_USB_ERR_BADDEVICE; -+ } -+ grub_dprintf("xhci", "%s: get slot %d assigned\n", __func__, slotid); -+ -+ grub_uint32_t size = (sizeof(struct grub_xhci_slotctx) * GRUB_XHCI_MAX_ENDPOINTS) << x->flag64; -+ -+ /* Allocate memory for the device specific slot context */ -+ priv->slotctx_dma = xhci_memalign_dma32(ALIGN_SLOTCTX, size, -+ x->pagesize); -+ if (!priv->slotctx_dma) -+ { -+ grub_dprintf("xhci", "%s: grub_memalign_dma32 failed\n", __func__); -+ grub_dma_free(reqs_dma); -+ grub_dma_free(in_dma); -+ return GRUB_USB_ERR_INTERNAL; -+ } -+ slotctx = grub_dma_get_virt(priv->slotctx_dma); -+ -+ grub_dprintf("xhci", "%s: enable slot: got slotid %d\n", __func__, slotid); -+ grub_memset((void *)slotctx, 0, size); -+ grub_arch_sync_dma_caches(slotctx, size); -+ -+ x->devs[slotid].ptr_low = grub_dma_get_phys(priv->slotctx_dma); -+ x->devs[slotid].ptr_high = 0; -+ grub_arch_sync_dma_caches(&x->devs[slotid], sizeof(x->devs[0])); -+ -+ /* Send set_address command. */ -+ int cc = xhci_cmd_address_device(x, slotid, in_dma); -+ if (cc != CC_SUCCESS) -+ { -+ grub_dprintf("xhci","%s: address device: failed (cc %d)\n", __func__, cc); -+ cc = xhci_cmd_disable_slot(x, slotid); -+ if (cc != CC_SUCCESS) { -+ grub_dprintf("xhci", "%s: disable failed (cc %d)\n", __func__, cc); -+ } else { -+ x->devs[slotid].ptr_low = 0; -+ x->devs[slotid].ptr_high = 0; -+ grub_arch_sync_dma_caches(&x->devs[slotid], sizeof(x->devs[0])); -+ } -+ grub_dma_free(priv->slotctx_dma); -+ grub_dma_free(reqs_dma); -+ grub_dma_free(in_dma); -+ return GRUB_USB_ERR_BADDEVICE; -+ } -+ priv->enpoint_trbs[epid] = reqs; -+ priv->enpoint_trbs_dma[epid] = reqs_dma; -+ priv->slotid = slotid; -+ priv->max_packet = 0; -+ } -+ if (epid != 1) -+ { -+ /* Send configure command. */ -+ int cc = xhci_cmd_configure_endpoint(x, priv->slotid, in_dma); -+ if (cc != CC_SUCCESS) -+ { -+ grub_dprintf("xhci", "%s: configure endpoint: failed (cc %d)\n", -+ __func__, cc); -+ grub_dma_free(reqs_dma); -+ grub_dma_free(in_dma); -+ return GRUB_USB_ERR_BADDEVICE; -+ } -+ priv->enpoint_trbs[epid] = reqs; -+ priv->enpoint_trbs_dma[epid] = reqs_dma; -+ } -+ -+ grub_dprintf("xhci", "%s: done\n", __func__); -+ grub_dma_free(in_dma); -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+ -+/**************************************************************** -+ * xHCI transfer helper functions -+ ****************************************************************/ -+ -+static grub_usb_err_t -+grub_xhci_usb_to_grub_err (unsigned char status) -+{ -+ if (status != CC_SUCCESS) -+ grub_dprintf("xhci", "%s: xfer failed (cc %d)\n", __func__, status); -+ else -+ grub_dprintf("xhci", "%s: xfer done (cc %d)\n", __func__, status); -+ -+ if (status == CC_BABBLE_DETECTED) -+ return GRUB_USB_ERR_BABBLE; -+ else if (status == CC_DATA_BUFFER_ERROR) -+ return GRUB_USB_ERR_DATA; -+ else if (status == CC_STALL_ERROR) -+ return GRUB_USB_ERR_STALL; -+ else if (status != CC_SUCCESS) -+ return GRUB_USB_ERR_NAK; -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+static int -+grub_xhci_transfer_is_zlp(grub_usb_transfer_t transfer, int idx) -+{ -+ if (idx >= transfer->transcnt) -+ return 0; -+ -+ grub_usb_transaction_t tr = &transfer->transactions[idx]; -+ -+ return (tr->size == 0) && -+ ((tr->pid == GRUB_USB_TRANSFER_TYPE_OUT) || -+ (tr->pid == GRUB_USB_TRANSFER_TYPE_IN)); -+} -+ -+static int -+grub_xhci_transfer_is_last(grub_usb_transfer_t transfer, int idx) -+{ -+ return (idx + 1) == transfer->transcnt; -+} -+ -+static int -+grub_xhci_transfer_is_data(grub_usb_transfer_t transfer, int idx) -+{ -+ grub_usb_transaction_t tr; -+ -+ if (idx >= transfer->transcnt) -+ return 0; -+ -+ tr = &transfer->transactions[idx]; -+ if (tr->size == 0 || -+ (tr->pid == GRUB_USB_TRANSFER_TYPE_SETUP)) -+ return 0; -+ -+ /* If there's are no DATA pakets before it's a DATA paket */ -+ for (int i = idx - 1; i >= 0; i--) -+ { -+ tr = &transfer->transactions[i]; -+ if (tr->size > 0 && -+ ((tr->pid == GRUB_USB_TRANSFER_TYPE_OUT) || -+ (tr->pid == GRUB_USB_TRANSFER_TYPE_IN))) -+ return 0; -+ } -+ return 1; -+} -+ -+static int -+grub_xhci_transfer_is_in(grub_usb_transfer_t transfer, int idx) -+{ -+ grub_usb_transaction_t tr; -+ -+ if (idx >= transfer->transcnt) -+ return 0; -+ -+ tr = &transfer->transactions[idx]; -+ -+ return tr->pid == GRUB_USB_TRANSFER_TYPE_IN; -+} -+ -+static int -+grub_xhci_transfer_is_normal(grub_usb_transfer_t transfer, int idx) -+{ -+ grub_usb_transaction_t tr; -+ -+ if (idx >= transfer->transcnt) -+ return 0; -+ -+ tr = &transfer->transactions[idx]; -+ if (tr->size == 0 || -+ (tr->pid == GRUB_USB_TRANSFER_TYPE_SETUP)) -+ return 0; -+ -+ /* If there's at least one DATA paket before it's a normal */ -+ for (int i = idx - 1; i >= 0; i--) -+ { -+ tr = &transfer->transactions[i]; -+ if (tr->size > 0 && -+ ((tr->pid == GRUB_USB_TRANSFER_TYPE_OUT) || -+ (tr->pid == GRUB_USB_TRANSFER_TYPE_IN))) -+ return 1; -+ -+ } -+ return 0; -+} -+ -+static int -+grub_xhci_transfer_next_is_normal(grub_usb_transfer_t transfer, int idx) -+{ -+ return grub_xhci_transfer_is_normal(transfer, idx + 1); -+} -+ -+static int -+grub_xhci_transfer_next_is_in(grub_usb_transfer_t transfer, int idx) -+{ -+ return grub_xhci_transfer_is_in(transfer, idx + 1); -+} -+ -+static grub_uint8_t grub_xhci_epid_from_transfer(grub_usb_transfer_t transfer) -+{ -+ grub_uint8_t epid; -+ -+ if (transfer->endpoint == 0) { -+ epid = 1; -+ } else { -+ epid = (transfer->endpoint & 0x0f) * 2; -+ epid += (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) ? 1 : 0; -+ } -+ return epid; -+} -+ -+/**************************************************************** -+ * xHCI transfer functions -+ ****************************************************************/ -+ -+static grub_usb_err_t -+grub_xhci_setup_transfer (grub_usb_controller_t dev, -+ grub_usb_transfer_t transfer) -+{ -+ struct grub_xhci_transfer_controller_data *cdata; -+ struct grub_xhci *x = (struct grub_xhci *) dev->data; -+ grub_uint8_t epid; -+ grub_usb_err_t err; -+ volatile struct grub_xhci_ring *reqs; -+ int rc; -+ struct grub_xhci_priv *priv; -+ -+ xhci_check_status(x); -+ -+ if (!dev || !transfer || !transfer->dev || !transfer->dev->xhci_priv) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ priv = transfer->dev->xhci_priv; -+ err = grub_xhci_prepare_endpoint(x, transfer->dev, -+ transfer->endpoint, -+ transfer->dir, -+ transfer->type, -+ transfer->max, -+ priv); -+ -+ if (err != GRUB_USB_ERR_NONE) -+ return err; -+ -+ epid = grub_xhci_epid_from_transfer(transfer); -+ -+ /* Update the max packet size once descdev.maxsize0 is valid */ -+ if (epid == 1 && -+ (priv->max_packet == 0) && -+ (transfer->dev->descdev.maxsize0 > 0)) -+ { -+ if (transfer->dev->speed == GRUB_USB_SPEED_SUPER) -+ priv->max_packet = 1UL << transfer->dev->descdev.maxsize0; -+ else -+ priv->max_packet = transfer->dev->descdev.maxsize0; -+ err = grub_xhci_update_max_paket_size(x, transfer, priv->slotid, priv->max_packet); -+ if (err != GRUB_USB_ERR_NONE) -+ { -+ grub_dprintf("xhci", "%s: Updating max paket size failed\n", __func__); -+ return err; -+ } -+ } -+ if (epid == 1 && -+ transfer->dev->descdev.class == 9 && -+ transfer->dev->nports > 0) -+ { -+ err = grub_xhci_update_hub_portcount(x, transfer, priv->slotid); -+ if (err != GRUB_USB_ERR_NONE) -+ { -+ grub_dprintf("xhci", "%s: Updating max paket size failed\n", __func__); -+ return err; -+ } -+ } -+ -+ /* Allocate private data for the transfer */ -+ cdata = grub_zalloc(sizeof(*cdata)); -+ if (!cdata) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ reqs = priv->enpoint_trbs[epid]; -+ -+ transfer->controller_data = cdata; -+ -+ /* Now queue the transfer onto the TRB */ -+ if (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL) -+ { -+ volatile struct grub_usb_packet_setup *setupdata; -+ setupdata = (void *)transfer->transactions[0].data; -+ grub_dprintf("xhci", "%s: CONTROLL TRANS req %d\n", __func__, setupdata->request); -+ grub_dprintf("xhci", "%s: CONTROLL TRANS length %d\n", __func__, setupdata->length); -+ -+ if (setupdata && setupdata->request == GRUB_USB_REQ_SET_ADDRESS) -+ return GRUB_USB_ERR_NONE; -+ -+ if (transfer->transcnt < 2) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ for (int i = 0; i < transfer->transcnt; i++) -+ { -+ grub_uint32_t flags = 0; -+ grub_uint64_t inline_data; -+ grub_usb_transaction_t tr = &transfer->transactions[i]; -+ -+ switch (tr->pid) -+ { -+ case GRUB_USB_TRANSFER_TYPE_SETUP: -+ { -+ grub_dprintf("xhci", "%s: SETUP PKG\n", __func__); -+ grub_dprintf("xhci", "%s: transfer->size %d\n", __func__, transfer->size); -+ grub_dprintf("xhci", "%s: tr->size %d SETUP PKG\n", __func__, tr->size); -+ -+ flags |= (TR_SETUP << 10); -+ flags |= TRB_TR_IDT; -+ -+ if (transfer->size > 0) -+ { -+ if (grub_xhci_transfer_next_is_in(transfer, i)) -+ flags |= (3 << 16); /* TRT IN */ -+ else -+ flags |= (2 << 16); /* TRT OUT */ -+ } -+ break; -+ } -+ case GRUB_USB_TRANSFER_TYPE_OUT: -+ { -+ grub_dprintf("xhci", "%s: OUT PKG\n", __func__); -+ cdata->transfer_size += tr->size; -+ break; -+ } -+ case GRUB_USB_TRANSFER_TYPE_IN: -+ { -+ grub_dprintf("xhci", "%s: IN PKG\n", __func__); -+ cdata->transfer_size += tr->size; -+ flags |= TRB_TR_DIR; -+ break; -+ } -+ } -+ -+ if (grub_xhci_transfer_is_normal(transfer, i)) -+ flags |= (TR_NORMAL << 10); -+ else if (grub_xhci_transfer_is_data(transfer, i)) -+ flags |= (TR_DATA << 10); -+ else if (grub_xhci_transfer_is_zlp(transfer, i)) -+ flags |= (TR_STATUS << 10); -+ -+ if (grub_xhci_transfer_next_is_normal(transfer, i)) -+ flags |= TRB_TR_CH; -+ -+ if (grub_xhci_transfer_is_last(transfer, i)) -+ flags |= TRB_TR_IOC; -+ -+ /* Assume the ring has enough free space for all TRBs */ -+ if (flags & TRB_TR_IDT && tr->size <= (int)sizeof(inline_data)) -+ { -+ grub_memcpy(&inline_data, (void *)tr->data, tr->size); -+ xhci_trb_queue(reqs, inline_data, tr->size, flags); -+ } -+ else -+ { -+ xhci_trb_queue(reqs, tr->data, tr->size, flags); -+ } -+ } -+ } -+ else if (transfer->type == GRUB_USB_TRANSACTION_TYPE_BULK) -+ { -+ for (int i = 0; i < transfer->transcnt; i++) -+ { -+ grub_uint32_t flags = (TR_NORMAL << 10); -+ grub_usb_transaction_t tr = &transfer->transactions[i]; -+ switch (tr->pid) -+ { -+ case GRUB_USB_TRANSFER_TYPE_OUT: -+ { -+ grub_dprintf("xhci", "%s: OUT PKG\n", __func__); -+ cdata->transfer_size += tr->size; -+ break; -+ } -+ case GRUB_USB_TRANSFER_TYPE_IN: -+ { -+ grub_dprintf("xhci", "%s: IN PKG\n", __func__); -+ cdata->transfer_size += tr->size; -+ flags |= TRB_TR_DIR; -+ break; -+ } -+ case GRUB_USB_TRANSFER_TYPE_SETUP: -+ break; -+ } -+ if (grub_xhci_transfer_is_last(transfer, i)) -+ flags |= TRB_TR_IOC; -+ -+ /* The ring might be to small, submit while adding new entries */ -+ rc = xhci_trb_queue_and_flush(x, priv->slotid, epid, -+ reqs, tr->data, tr->size, flags); -+ if (rc < 0) -+ return GRUB_USB_ERR_TIMEOUT; -+ else if (rc > 1) -+ return grub_xhci_usb_to_grub_err(rc); -+ -+ } -+ } -+ xhci_doorbell(x, priv->slotid, epid); -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+static grub_usb_err_t -+grub_xhci_check_transfer (grub_usb_controller_t dev, -+ grub_usb_transfer_t transfer, grub_size_t * actual) -+{ -+ grub_uint32_t status; -+ grub_uint32_t remaining; -+ grub_uint8_t epid; -+ volatile struct grub_xhci_ring *reqs; -+ grub_usb_err_t err; -+ int rc; -+ -+ if (!dev->data || !transfer->controller_data || !transfer->dev || -+ !transfer->dev->xhci_priv) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ -+ struct grub_xhci_priv *priv = transfer->dev->xhci_priv; -+ struct grub_xhci *x = (struct grub_xhci *) dev->data; -+ struct grub_xhci_transfer_controller_data *cdata = -+ transfer->controller_data; -+ -+ xhci_check_status(x); -+ xhci_process_events(x); -+ -+ epid = grub_xhci_epid_from_transfer(transfer); -+ -+ reqs = priv->enpoint_trbs[epid]; -+ -+ /* XXX: invalidate caches */ -+ -+ /* Get current status from event ring buffer */ -+ status = (reqs->evt.status>> 24) & 0xff; -+ remaining = reqs->evt.status & 0xffffff; -+ -+ if (status != CC_STOPPED_LENGTH_INVALID) -+ *actual = cdata->transfer_size - remaining; -+ else -+ *actual = 0; -+ -+ if (xhci_ring_busy(reqs)) -+ return GRUB_USB_ERR_WAIT; -+ -+ grub_free(cdata); -+ -+ grub_dprintf("xhci", "%s: xfer done\n", __func__); -+ -+ err = grub_xhci_usb_to_grub_err(status); -+ if (err != GRUB_USB_ERR_NONE) -+ { -+ if (status == CC_STALL_ERROR) -+ { -+ /* Clear the stall by resetting the endpoint */ -+ rc = xhci_cmd_reset_endpoint(x, priv->slotid, epid, 1); -+ -+ if (rc < 0) -+ return GRUB_USB_ERR_TIMEOUT; -+ -+ return GRUB_USB_ERR_STALL; -+ } -+ else if (remaining > 0) -+ { -+ return GRUB_USB_ERR_DATA; -+ } -+ } -+ -+ return err; -+} -+ -+static grub_usb_err_t -+grub_xhci_cancel_transfer (grub_usb_controller_t dev, -+ grub_usb_transfer_t transfer) -+{ -+ grub_uint8_t epid; -+ volatile struct grub_xhci_ring *reqs; -+ struct grub_pci_dma_chunk *enpoint_trbs_dma; -+ grub_addr_t deque_pointer; -+ int rc; -+ -+ if (!dev->data || !transfer->controller_data || !transfer->dev || -+ !transfer->dev->xhci_priv) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ struct grub_xhci *x = (struct grub_xhci *) dev->data; -+ struct grub_xhci_transfer_controller_data *cdata = -+ transfer->controller_data; -+ struct grub_xhci_priv *priv = transfer->dev->xhci_priv; -+ -+ epid = grub_xhci_epid_from_transfer(transfer); -+ -+ enpoint_trbs_dma = priv->enpoint_trbs_dma[epid]; -+ reqs = priv->enpoint_trbs[epid]; -+ -+ /* Abort current command */ -+ rc = xhci_cmd_stop_endpoint(x, priv->slotid, epid, 0); -+ if (rc < 0) -+ return GRUB_USB_ERR_TIMEOUT; -+ -+ /* Reset state */ -+ reqs->nidx = 0; -+ reqs->eidx = 0; -+ reqs->cs = 1; -+ -+ grub_arch_sync_dma_caches(reqs, sizeof(*reqs)); -+ -+ /* Reset the dequeue pointer to the begging of the TRB */ -+ deque_pointer = grub_dma_get_phys(enpoint_trbs_dma); -+ rc = xhci_cmd_set_dequeue_pointer(x, priv->slotid, epid, deque_pointer| 1 ); -+ if (rc < 0) -+ return GRUB_USB_ERR_TIMEOUT; -+ -+ reqs->evt.ptr_low = 0; -+ reqs->evt.ptr_high = 0; -+ reqs->evt.control = 0; -+ reqs->evt.status = 0; -+ -+ grub_arch_sync_dma_caches(reqs, sizeof(*reqs)); -+ -+ /* Restart ring buffer processing */ -+ xhci_doorbell(x, priv->slotid, epid); -+ -+ grub_free (cdata); -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+/**************************************************************** -+ * xHCI port status functions -+ ****************************************************************/ -+ -+static int -+grub_xhci_hubports (grub_usb_controller_t dev) -+{ -+ struct grub_xhci *x = (struct grub_xhci *) dev->data; -+ grub_uint32_t portinfo; -+ -+ portinfo = x->ports; -+ grub_dprintf ("xhci", "root hub ports=%d\n", portinfo); -+ return portinfo; -+} -+ -+static grub_usb_err_t -+grub_xhci_portstatus (grub_usb_controller_t dev, -+ unsigned int port, unsigned int enable) -+{ -+ struct grub_xhci *x = (struct grub_xhci *) dev->data; -+ grub_uint32_t portsc, pls; -+ grub_uint32_t end; -+ -+ portsc = grub_xhci_port_read(x, port); -+ pls = xhci_get_field(portsc, XHCI_PORTSC_PLS); -+ -+ grub_dprintf("xhci", "grub_xhci_portstatus port #%d: 0x%08x,%s%s pls %d enable %d\n", -+ port, portsc, -+ (portsc & GRUB_XHCI_PORTSC_PP) ? " powered," : "", -+ (portsc & GRUB_XHCI_PORTSC_PED) ? " enabled," : "", -+ pls, enable); -+ xhci_check_status(x); -+ -+ if ((enable && (portsc & GRUB_XHCI_PORTSC_PED)) || -+ (!enable && !(portsc & GRUB_XHCI_PORTSC_PED))) -+ return GRUB_USB_ERR_NONE; -+ -+ if (!enable) -+ { -+ /* Disable port */ -+ grub_xhci_port_write(x, port, ~0, GRUB_XHCI_PORTSC_PED); -+ return GRUB_USB_ERR_NONE; -+ } -+ -+ grub_dprintf ("xhci", "portstatus: XHCI STATUS: %08x\n", -+ grub_xhci_read32(&x->op->usbsts)); -+ grub_dprintf ("xhci", -+ "portstatus: begin, iobase=%p, port=%d, status=0x%08x\n", -+ x->caps, port, portsc); -+ -+ switch (pls) -+ { -+ case PLS_U0: -+ /* A USB3 port - controller automatically performs reset */ -+ break; -+ case PLS_POLLING: -+ /* A USB2 port - perform device reset */ -+ grub_xhci_port_write(x, port, ~GRUB_XHCI_PORTSC_PED, GRUB_XHCI_PORTSC_PR); -+ break; -+ default: -+ return GRUB_USB_ERR_NONE; -+ } -+ -+ /* Wait for device to complete reset and be enabled */ -+ end = grub_get_time_ms () + 100; -+ for (;;) -+ { -+ portsc = grub_xhci_port_read(x, port); -+ if (!(portsc & GRUB_XHCI_PORTSC_CCS)) -+ { -+ /* Device disconnected during reset */ -+ grub_dprintf ("xhci","ERROR: %s device disconnected\n", __func__); -+ return GRUB_USB_ERR_BADDEVICE; -+ } -+ if (portsc & GRUB_XHCI_PORTSC_PED) -+ /* Reset complete */ -+ break; -+ if (grub_get_time_ms () > end) -+ { -+ grub_dprintf ("xhci","ERROR: %s TIMEOUT\n", __func__); -+ return GRUB_USB_ERR_TIMEOUT; -+ } -+ } -+ xhci_check_status(x); -+ -+ return GRUB_USB_ERR_NONE; -+} -+ -+/**************************************************************** -+ * xHCI detect device functions -+ ****************************************************************/ -+ -+static grub_usb_speed_t -+grub_xhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) -+{ -+ struct grub_xhci *x = (struct grub_xhci *) dev->data; -+ grub_uint32_t portsc, speed; -+ -+ *changed = 0; -+ grub_dprintf("xhci", "%s: dev=%p USB%d_%d port %d\n", __func__, dev, -+ x->psids[port-1].major, x->psids[port-1].minor, port); -+ -+ /* On shutdown advertise all ports as disconnected. This will trigger -+ * a gracefull detatch. */ -+ if (x->shutdown) -+ { -+ *changed = 1; -+ return GRUB_USB_SPEED_NONE; -+ } -+ -+ /* Don't advertise new devices, connecting will fail if halted */ -+ if (xhci_is_halted(x)) -+ return GRUB_USB_SPEED_NONE; -+ -+ portsc = grub_xhci_port_read(x, port); -+ speed = xhci_get_field(portsc, XHCI_PORTSC_SPEED); -+ grub_uint8_t pls = xhci_get_field(portsc, XHCI_PORTSC_PLS); -+ -+ grub_dprintf("xhci", "grub_xhci_portstatus port #%d: 0x%08x,%s%s pls %d\n", -+ port, portsc, -+ (portsc & GRUB_XHCI_PORTSC_PP) ? " powered," : "", -+ (portsc & GRUB_XHCI_PORTSC_PED) ? " enabled," : "", -+ pls); -+ -+ /* Connect Status Change bit - it detects change of connection */ -+ if (portsc & GRUB_XHCI_PORTSC_CSC) -+ { -+ *changed = 1; -+ -+ grub_xhci_port_write(x, port, ~GRUB_XHCI_PORTSC_PED, GRUB_XHCI_PORTSC_CSC); -+ } -+ -+ if (!(portsc & GRUB_XHCI_PORTSC_CCS)) -+ return GRUB_USB_SPEED_NONE; -+ -+ for (grub_uint8_t i = 0; i < 16 && x->psids[port-1].psids[i].id > 0; i++) -+ { -+ if (x->psids[port-1].psids[i].id == speed) -+ { -+ grub_dprintf("xhci", "%s: grub_usb_speed = %d\n", __func__, -+ x->psids[port-1].psids[i].grub_usb_speed ); -+ return x->psids[port-1].psids[i].grub_usb_speed; -+ } -+ } -+ -+ return GRUB_USB_SPEED_NONE; -+} -+ -+/**************************************************************** -+ * xHCI attach/detach functions -+ ****************************************************************/ -+ -+static grub_usb_err_t -+grub_xhci_attach_dev (grub_usb_controller_t ctrl, grub_usb_device_t dev) -+{ -+ struct grub_xhci *x = (struct grub_xhci *) ctrl->data; -+ grub_usb_err_t err; -+ grub_uint32_t max; -+ -+ grub_dprintf("xhci", "%s: dev=%p\n", __func__, dev); -+ -+ if (!dev || !x) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ dev->xhci_priv = grub_zalloc (sizeof (struct grub_xhci_priv)); -+ if (!dev->xhci_priv) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ -+ switch (dev->speed) -+ { -+ case GRUB_USB_SPEED_LOW: -+ { -+ max = 8; -+ break; -+ } -+ case GRUB_USB_SPEED_FULL: -+ case GRUB_USB_SPEED_HIGH: -+ { -+ max = 64; -+ break; -+ } -+ case GRUB_USB_SPEED_SUPER: -+ { -+ max = 512; -+ break; -+ } -+ default: -+ case GRUB_USB_SPEED_NONE: -+ { -+ max = 0; -+ } -+ } -+ -+ /* Assign a slot, assign an address and configure endpoint 0 */ -+ err = grub_xhci_prepare_endpoint(x, dev, -+ 0, -+ 0, -+ GRUB_USB_TRANSACTION_TYPE_CONTROL, -+ max, -+ dev->xhci_priv); -+ -+ return err; -+} -+ -+static grub_usb_err_t -+grub_xhci_detach_dev (grub_usb_controller_t ctrl, grub_usb_device_t dev) -+{ -+ struct grub_xhci *x = (struct grub_xhci *) ctrl->data; -+ struct grub_xhci_priv *priv; -+ int cc = CC_SUCCESS; -+ -+ grub_dprintf("xhci", "%s: dev=%p\n", __func__, dev); -+ -+ if (!dev) -+ return GRUB_USB_ERR_INTERNAL; -+ -+ if (dev->xhci_priv) -+ { -+ priv = dev->xhci_priv; -+ /* Stop endpoints and free ring buffer */ -+ for (int i = 0; i < GRUB_XHCI_MAX_ENDPOINTS; i++) -+ { -+ if (priv->enpoint_trbs[i] != NULL) -+ { -+ cc = xhci_cmd_stop_endpoint(x, priv->slotid, i, 1); -+ if (cc != CC_SUCCESS) -+ grub_dprintf("xhci", "Failed to disable EP%d on slot %d\n", i, -+ priv->slotid); -+ -+ grub_dprintf("xhci", "grub_dma_free[%d]\n", i); -+ -+ grub_dma_free(priv->enpoint_trbs_dma[i]); -+ priv->enpoint_trbs[i] = NULL; -+ priv->enpoint_trbs_dma[i] = NULL; -+ } -+ } -+ -+ cc = xhci_cmd_disable_slot(x, priv->slotid); -+ if (cc == CC_SUCCESS) -+ { -+ if (priv->slotctx_dma) -+ grub_dma_free(priv->slotctx_dma); -+ x->devs[priv->slotid].ptr_low = 0; -+ x->devs[priv->slotid].ptr_high = 0; -+ grub_arch_sync_dma_caches(&x->devs[priv->slotid], sizeof(x->devs[0])); -+ } -+ else -+ grub_dprintf("xhci", "Failed to disable slot %d\n", priv->slotid); -+ -+ grub_free(dev->xhci_priv); -+ } -+ -+ dev->xhci_priv = NULL; -+ -+ if (cc != CC_SUCCESS) -+ return GRUB_USB_ERR_BADDEVICE; -+ return GRUB_USB_ERR_NONE; -+} -+ -+/**************************************************************** -+ * xHCI terminate functions -+ ****************************************************************/ -+ -+static void -+grub_xhci_halt(struct grub_xhci *x) -+{ -+ grub_uint32_t reg; -+ -+ /* Halt the command ring */ -+ reg = grub_xhci_read32(&x->op->crcr_low); -+ grub_xhci_write32(&x->op->crcr_low, reg | 4); -+ -+ int rc = xhci_event_wait(x, x->cmds, 100); -+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc); -+ if (rc < 0) -+ return; -+ -+ /* Stop the controller */ -+ reg = grub_xhci_read32(&x->op->usbcmd); -+ if (reg & GRUB_XHCI_CMD_RS) -+ { -+ reg &= ~GRUB_XHCI_CMD_RS; -+ grub_xhci_write32(&x->op->usbcmd, reg); -+ } -+ -+ return; -+} -+ -+static grub_err_t -+grub_xhci_fini_hw (int noreturn __attribute__ ((unused))) -+{ -+ struct grub_xhci *x; -+ -+ /* We should disable all XHCI HW to prevent any DMA access etc. */ -+ for (x = xhci; x; x = x->next) -+ { -+ x->shutdown = 1; -+ -+ /* Gracefully detach active devices */ -+ grub_usb_poll_devices(0); -+ -+ /* Check if xHCI is halted and halt it if not */ -+ grub_xhci_halt (x); -+ -+ /* Reset xHCI */ -+ if (grub_xhci_reset (x) != GRUB_USB_ERR_NONE) -+ return GRUB_ERR_BAD_DEVICE; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static struct grub_usb_controller_dev usb_controller = { -+ .name = "xhci", -+ .iterate = grub_xhci_iterate, -+ .setup_transfer = grub_xhci_setup_transfer, -+ .check_transfer = grub_xhci_check_transfer, -+ .cancel_transfer = grub_xhci_cancel_transfer, -+ .hubports = grub_xhci_hubports, -+ .portstatus = grub_xhci_portstatus, -+ .detect_dev = grub_xhci_detect_dev, -+ .attach_dev = grub_xhci_attach_dev, -+ .detach_dev = grub_xhci_detach_dev, -+ /* estimated max. count of TDs for one bulk transfer */ -+ .max_bulk_tds = GRUB_XHCI_RING_ITEMS - 3 -+}; -+ -+GRUB_MOD_INIT (xhci) -+{ -+ grub_stop_disk_firmware (); -+ -+ grub_boot_time ("Initing XHCI hardware"); -+ grub_xhci_pci_scan (); -+ grub_boot_time ("Registering XHCI driver"); -+ grub_usb_controller_dev_register (&usb_controller); -+ grub_boot_time ("XHCI driver registered"); -+} -+ -+GRUB_MOD_FINI (xhci) -+{ -+ grub_xhci_fini_hw (0); -+ grub_usb_controller_dev_unregister (&usb_controller); -+} -diff --git a/include/grub/usb.h b/include/grub/usb.h -index 609faf7d0..eb71fa1c7 100644 ---- a/include/grub/usb.h -+++ b/include/grub/usb.h -@@ -338,6 +338,10 @@ grub_usb_cancel_transfer (grub_usb_transfer_t trans); - void - grub_ehci_init_device (volatile void *regs); - void -+grub_xhci_init_device (volatile void *regs); -+void - grub_ehci_pci_scan (void); -+void -+grub_xhci_pci_scan (void); - - #endif /* GRUB_USB_H */ --- -2.39.5 - diff --git a/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch b/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch deleted file mode 100644 index 31e831ec..00000000 --- a/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch +++ /dev/null @@ -1,127 +0,0 @@ -From d84ac94dc55baad9a2297980b2017cd22e4ecb3c Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Mon, 7 Dec 2020 08:41:27 +0100 -Subject: [PATCH 20/26] grub-core/bus/usb/usbhub: Add xHCI non root hub support - -Tested on Intel PCH C246, the USB3 hub can be configured by grub. - -Issues: -* USB3 devices connected behind that hub are sometimes not detected. - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> ---- - grub-core/bus/usb/usbhub.c | 38 +++++++++++++++++++++++++++++++++----- - include/grub/usbdesc.h | 1 + - include/grub/usbtrans.h | 4 ++++ - 3 files changed, 38 insertions(+), 5 deletions(-) - -diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c -index b4b3a1a61..e96505aa9 100644 ---- a/grub-core/bus/usb/usbhub.c -+++ b/grub-core/bus/usb/usbhub.c -@@ -148,19 +148,32 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, - return dev; - } - -- -+static grub_usb_err_t -+grub_usb_set_hub_depth(grub_usb_device_t dev, grub_uint8_t depth) -+{ -+ return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT -+ | GRUB_USB_REQTYPE_CLASS -+ | GRUB_USB_REQTYPE_TARGET_DEV), -+ GRUB_USB_HUB_REQ_SET_HUB_DEPTH, depth, -+ 0, 0, NULL); -+} -+ - static grub_usb_err_t - grub_usb_add_hub (grub_usb_device_t dev) - { - struct grub_usb_usb_hubdesc hubdesc; - grub_usb_err_t err; -+ grub_uint16_t req; - int i; - -+ req = (dev->speed == GRUB_USB_SPEED_SUPER) ? GRUB_USB_DESCRIPTOR_SS_HUB : -+ GRUB_USB_DESCRIPTOR_HUB; -+ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_DEV), -- GRUB_USB_REQ_GET_DESCRIPTOR, -- (GRUB_USB_DESCRIPTOR_HUB << 8) | 0, -+ GRUB_USB_REQ_GET_DESCRIPTOR, -+ (req << 8) | 0, - 0, sizeof (hubdesc), (char *) &hubdesc); - if (err) - return err; -@@ -183,6 +196,19 @@ grub_usb_add_hub (grub_usb_device_t dev) - return GRUB_USB_ERR_INTERNAL; - } - -+ if (dev->speed == GRUB_USB_SPEED_SUPER) -+ { -+ grub_uint8_t depth; -+ grub_uint32_t route; -+ /* Depth maximum value is 5, but root hubs doesn't count */ -+ for (depth = 0, route = dev->route; (route & 0xf) > 0; route >>= 4) -+ depth++; -+ -+ err = grub_usb_set_hub_depth(dev, depth); -+ if (err) -+ return err; -+ } -+ - /* Power on all Hub ports. */ - for (i = 1; i <= hubdesc.portcnt; i++) - { -@@ -637,7 +663,9 @@ poll_nonroot_hub (grub_usb_device_t dev) - int split_hubaddr = 0; - - /* Determine the device speed. */ -- if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) -+ if (dev->speed == GRUB_USB_SPEED_SUPER) -+ speed = GRUB_USB_SPEED_SUPER; -+ else if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) - speed = GRUB_USB_SPEED_LOW; - else - { -@@ -651,7 +679,7 @@ poll_nonroot_hub (grub_usb_device_t dev) - grub_millisleep (10); - - /* Find correct values for SPLIT hubport and hubaddr */ -- if (speed == GRUB_USB_SPEED_HIGH) -+ if (speed == GRUB_USB_SPEED_HIGH || speed == GRUB_USB_SPEED_SUPER) - { - /* HIGH speed device needs not transaction translation */ - split_hubport = 0; -diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h -index bb2ab2e27..1697aa465 100644 ---- a/include/grub/usbdesc.h -+++ b/include/grub/usbdesc.h -@@ -30,6 +30,7 @@ typedef enum { - GRUB_USB_DESCRIPTOR_ENDPOINT, - GRUB_USB_DESCRIPTOR_DEBUG = 10, - GRUB_USB_DESCRIPTOR_HUB = 0x29, -+ GRUB_USB_DESCRIPTOR_SS_HUB = 0x2a, - GRUB_USB_DESCRIPTOR_SS_ENDPOINT_COMPANION = 0x30 - } grub_usb_descriptor_t; - -diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h -index 039ebed65..d6c3f71dc 100644 ---- a/include/grub/usbtrans.h -+++ b/include/grub/usbtrans.h -@@ -110,6 +110,10 @@ enum - GRUB_USB_REQ_SET_INTERFACE = 0x0B, - GRUB_USB_REQ_SYNC_FRAME = 0x0C - }; -+enum -+ { -+ GRUB_USB_HUB_REQ_SET_HUB_DEPTH = 0x0C, -+ }; - - #define GRUB_USB_FEATURE_ENDP_HALT 0x00 - #define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01 --- -2.39.5 - diff --git a/config/grub/xhci/patches/0021-xHCI-also-accept-SBRN-0x31-and-0x32.patch b/config/grub/xhci/patches/0021-xHCI-also-accept-SBRN-0x31-and-0x32.patch deleted file mode 100644 index f6e0f366..00000000 --- a/config/grub/xhci/patches/0021-xHCI-also-accept-SBRN-0x31-and-0x32.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0433c5bb1e40fba93205e1c9fd6b1b397d31ae5a Mon Sep 17 00:00:00 2001 -From: Sven Anderson <sven@anderson.de> -Date: Sat, 28 May 2022 21:39:23 +0200 -Subject: [PATCH 21/26] xHCI: also accept SBRN 0x31 and 0x32 - -Signed-off-by: Sven Anderson <sven@anderson.de> ---- - grub-core/bus/usb/xhci-pci.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grub-core/bus/usb/xhci-pci.c b/grub-core/bus/usb/xhci-pci.c -index a5bd3c97d..cde21f57a 100644 ---- a/grub-core/bus/usb/xhci-pci.c -+++ b/grub-core/bus/usb/xhci-pci.c -@@ -76,7 +76,7 @@ grub_xhci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, - /* Check Serial Bus Release Number */ - addr = grub_pci_make_address (dev, GRUB_XHCI_PCI_SBRN_REG); - release = grub_pci_read_byte (addr); -- if (release != 0x30) -+ if (release != 0x30 && release != 0x31 &&release != 0x32) - { - grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: Wrong SBRN: %0x\n", - release); --- -2.39.5 - diff --git a/config/grub/xhci/patches/0022-xhci-fix-port-indexing.patch b/config/grub/xhci/patches/0022-xhci-fix-port-indexing.patch deleted file mode 100644 index edfcca2c..00000000 --- a/config/grub/xhci/patches/0022-xhci-fix-port-indexing.patch +++ /dev/null @@ -1,43 +0,0 @@ -From d300f12cb624998f3d5ab5948c3fc64d6d7baf4f Mon Sep 17 00:00:00 2001 -From: Sven Anderson <sven@anderson.de> -Date: Mon, 13 Jan 2025 19:51:41 +0100 -Subject: [PATCH 22/26] xhci: fix port indexing - ---- - grub-core/bus/usb/xhci.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c -index f4591ffb5..dc89b9619 100644 ---- a/grub-core/bus/usb/xhci.c -+++ b/grub-core/bus/usb/xhci.c -@@ -2250,7 +2250,7 @@ grub_xhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) - - *changed = 0; - grub_dprintf("xhci", "%s: dev=%p USB%d_%d port %d\n", __func__, dev, -- x->psids[port-1].major, x->psids[port-1].minor, port); -+ x->psids[port].major, x->psids[port].minor, port); - - /* On shutdown advertise all ports as disconnected. This will trigger - * a gracefull detatch. */ -@@ -2285,13 +2285,13 @@ grub_xhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) - if (!(portsc & GRUB_XHCI_PORTSC_CCS)) - return GRUB_USB_SPEED_NONE; - -- for (grub_uint8_t i = 0; i < 16 && x->psids[port-1].psids[i].id > 0; i++) -+ for (grub_uint8_t i = 0; i < 16 && x->psids[port].psids[i].id > 0; i++) - { -- if (x->psids[port-1].psids[i].id == speed) -+ if (x->psids[port].psids[i].id == speed) - { - grub_dprintf("xhci", "%s: grub_usb_speed = %d\n", __func__, -- x->psids[port-1].psids[i].grub_usb_speed ); -- return x->psids[port-1].psids[i].grub_usb_speed; -+ x->psids[port].psids[i].grub_usb_speed ); -+ return x->psids[port].psids[i].grub_usb_speed; - } - } - --- -2.39.5 - diff --git a/config/grub/xhci/patches/0023-xhci-configure-TT-for-non-root-hubs.patch b/config/grub/xhci/patches/0023-xhci-configure-TT-for-non-root-hubs.patch deleted file mode 100644 index b41db45f..00000000 --- a/config/grub/xhci/patches/0023-xhci-configure-TT-for-non-root-hubs.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0a669ef9815267de4fb14f3c329431ac531755c9 Mon Sep 17 00:00:00 2001 -From: Sven Anderson <sven@anderson.de> -Date: Mon, 13 Jan 2025 20:26:32 +0100 -Subject: [PATCH 23/26] xhci: configure TT for non-root-hubs - ---- - grub-core/bus/usb/usbhub.c | 6 +++++ - grub-core/bus/usb/xhci.c | 45 +++++++++++++++++++++++++++++++++----- - include/grub/usb.h | 2 ++ - 3 files changed, 47 insertions(+), 6 deletions(-) - -diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c -index e96505aa9..629b3ed53 100644 ---- a/grub-core/bus/usb/usbhub.c -+++ b/grub-core/bus/usb/usbhub.c -@@ -818,3 +818,9 @@ grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data) - - return 0; - } -+ -+grub_usb_device_t -+grub_usb_get_dev (int addr) -+{ -+ return grub_usb_devs[addr]; -+} -diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c -index dc89b9619..88c9ac57f 100644 ---- a/grub-core/bus/usb/xhci.c -+++ b/grub-core/bus/usb/xhci.c -@@ -623,13 +623,46 @@ grub_xhci_alloc_inctx(struct grub_xhci *x, int maxepid, - break; - } - -- /* Route is greater zero on devices that are connected to a non root hub */ -- if (dev->route) -- { -- /* FIXME: Implement this code for non SuperSpeed hub devices */ -+ /* Set routing string */ -+ slot->ctx[0] |= dev->route; -+ -+ /* Set root hub port number */ -+ slot->ctx[1] |= (dev->root_port + 1) << 16; -+ -+ if (dev->split_hubaddr && (dev->speed == GRUB_USB_SPEED_LOW || -+ dev->speed == GRUB_USB_SPEED_FULL)) { -+ -+ grub_usb_device_t hubdev = grub_usb_get_dev(dev->split_hubaddr); -+ -+ if (!hubdev || hubdev->descdev.class != GRUB_USB_CLASS_HUB) { -+ grub_dprintf("xhci", "Invalid hub device at addr %d!\n", dev->split_hubaddr); -+ return NULL; -+ } -+ -+ struct grub_xhci_priv *hub_priv = hubdev->xhci_priv; -+ if (!hub_priv) { -+ grub_dprintf("xhci", "Hub has no xhci_priv!\n"); -+ return NULL; -+ } -+ -+ if (hubdev->speed == GRUB_USB_SPEED_HIGH) { -+ /* Direct connection to high-speed hub - set up TT */ -+ grub_dprintf("xhci", "Direct high-speed hub connection - configuring TT with " -+ "hub slot %d port %d\n", hub_priv->slotid, dev->split_hubport); -+ slot->ctx[2] |= hub_priv->slotid; -+ slot->ctx[2] |= dev->split_hubport << 8; - } -- slot->ctx[0] |= dev->route; -- slot->ctx[1] |= (dev->root_port+1) << 16; -+ else { -+ /* Hub is not high-speed, inherit TT settings from parent */ -+ volatile struct grub_xhci_slotctx *hubslot; -+ grub_dprintf("xhci", "Non high-speed hub - inheriting TT settings from parent\n"); -+ hubslot = grub_dma_phys2virt(x->devs[hub_priv->slotid].ptr_low, x->devs_dma); -+ slot->ctx[2] = hubslot->ctx[2]; -+ } -+ } -+ -+ grub_dprintf("xhci", "Slot context: ctx[0]=0x%08x ctx[1]=0x%08x ctx[2]=0x%08x\n", -+ slot->ctx[0], slot->ctx[1], slot->ctx[2]); - - grub_arch_sync_dma_caches(in, size); - -diff --git a/include/grub/usb.h b/include/grub/usb.h -index eb71fa1c7..df97a60cc 100644 ---- a/include/grub/usb.h -+++ b/include/grub/usb.h -@@ -62,6 +62,8 @@ typedef int (*grub_usb_controller_iterate_hook_t) (grub_usb_controller_t dev, - /* Call HOOK with each device, until HOOK returns non-zero. */ - int grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data); - -+grub_usb_device_t grub_usb_get_dev (int addr); -+ - grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev); - - grub_usb_err_t grub_usb_get_descriptor (grub_usb_device_t dev, --- -2.39.5 - diff --git a/config/grub/xhci/patches/0024-Fix-compilation-on-x86_64.patch b/config/grub/xhci/patches/0024-Fix-compilation-on-x86_64.patch deleted file mode 100644 index cdc692d6..00000000 --- a/config/grub/xhci/patches/0024-Fix-compilation-on-x86_64.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 625fdcf42f2cf11a4bfe644412450c9e4f551d25 Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Wed, 24 Feb 2021 08:25:41 +0100 -Subject: [PATCH 24/26] Fix compilation on x86_64 - -Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> ---- - grub-core/bus/usb/xhci.c | 24 ++++++++++++++++-------- - 1 file changed, 16 insertions(+), 8 deletions(-) - -diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c -index 88c9ac57f..9b9bae6e5 100644 ---- a/grub-core/bus/usb/xhci.c -+++ b/grub-core/bus/usb/xhci.c -@@ -184,7 +184,7 @@ enum - * then we can get it from a trb pointer (provided by evt ring). - */ - #define XHCI_RING(_trb) \ -- ((struct grub_xhci_ring*)((grub_uint32_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1))) -+ ((struct grub_xhci_ring*)((grub_addr_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1))) - - /* slot context */ - struct grub_xhci_slotctx { -@@ -495,6 +495,14 @@ grub_xhci_read8(volatile void *addr) { - return (*((volatile grub_uint32_t *)addr)); - } - -+static inline void * -+grub_xhci_read_etrb_ptr(volatile struct grub_xhci_trb *trb) { -+ grub_uint64_t tmp; -+ tmp = (grub_uint64_t)grub_xhci_read32(&trb->ptr_low); -+ tmp |= ((grub_uint64_t)grub_xhci_read32(&trb->ptr_high)) << 32; -+ return (void *)(grub_addr_t)tmp; -+} -+ - static inline grub_uint32_t - grub_xhci_port_read (struct grub_xhci *x, grub_uint32_t port) - { -@@ -697,7 +705,7 @@ static void xhci_process_events(struct grub_xhci *x) - case ER_TRANSFER: - case ER_COMMAND_COMPLETE: - { -- struct grub_xhci_trb *rtrb = (void*)grub_xhci_read32(&etrb->ptr_low); -+ struct grub_xhci_trb *rtrb = grub_xhci_read_etrb_ptr(etrb); - struct grub_xhci_ring *ring = XHCI_RING(rtrb); - volatile struct grub_xhci_trb *evt = &ring->evt; - grub_uint32_t eidx = rtrb - ring->ring + 1; -@@ -730,9 +738,9 @@ static void xhci_process_events(struct grub_xhci *x) - } - grub_xhci_write32(&evts->nidx, nidx); - volatile struct grub_xhci_ir *ir = x->ir; -- grub_uint32_t erdp = (grub_uint32_t)(evts->ring + nidx); -- grub_xhci_write32(&ir->erdp_low, erdp); -- grub_xhci_write32(&ir->erdp_high, 0); -+ grub_uint64_t erdp = (grub_addr_t)(void *)(&evts->ring[nidx]); -+ grub_xhci_write32(&ir->erdp_low, erdp & 0xffffffff); -+ grub_xhci_write32(&ir->erdp_high, erdp >> 32); - } - } - -@@ -833,7 +841,7 @@ static void xhci_trb_queue(volatile struct grub_xhci_ring *ring, - grub_uint32_t xferlen, grub_uint32_t flags) - { - grub_dprintf("xhci", "%s: ring %p data %llx len %d flags 0x%x remain 0x%x\n", __func__, -- ring, data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17); -+ ring, (unsigned long long)data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17); - - if (xhci_ring_full(ring)) - { -@@ -1940,7 +1948,7 @@ grub_xhci_setup_transfer (grub_usb_controller_t dev, - if (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL) - { - volatile struct grub_usb_packet_setup *setupdata; -- setupdata = (void *)transfer->transactions[0].data; -+ setupdata = (void *)(grub_addr_t)transfer->transactions[0].data; - grub_dprintf("xhci", "%s: CONTROLL TRANS req %d\n", __func__, setupdata->request); - grub_dprintf("xhci", "%s: CONTROLL TRANS length %d\n", __func__, setupdata->length); - -@@ -2007,7 +2015,7 @@ grub_xhci_setup_transfer (grub_usb_controller_t dev, - /* Assume the ring has enough free space for all TRBs */ - if (flags & TRB_TR_IDT && tr->size <= (int)sizeof(inline_data)) - { -- grub_memcpy(&inline_data, (void *)tr->data, tr->size); -+ grub_memcpy(&inline_data, (void *)(grub_addr_t)tr->data, tr->size); - xhci_trb_queue(reqs, inline_data, tr->size, flags); - } - else --- -2.39.5 - diff --git a/config/grub/xhci/patches/0025-Add-native-NVMe-driver-based-on-SeaBIOS.patch b/config/grub/xhci/patches/0025-Add-native-NVMe-driver-based-on-SeaBIOS.patch deleted file mode 100644 index e9dc54b5..00000000 --- a/config/grub/xhci/patches/0025-Add-native-NVMe-driver-based-on-SeaBIOS.patch +++ /dev/null @@ -1,1074 +0,0 @@ -From 1ede42b39a87ccb2cc43d919f3ee4803d6551102 Mon Sep 17 00:00:00 2001 -From: Mate Kukri <km@mkukri.xyz> -Date: Mon, 20 May 2024 11:43:35 +0100 -Subject: [PATCH 25/26] Add native NVMe driver based on SeaBIOS - -Tested to successfully boot Debian on QEMU and OptiPlex 3050. - -Signed-off-by: Mate Kukri <km@mkukri.xyz> ---- - Makefile.am | 2 +- - grub-core/Makefile.core.def | 6 + - grub-core/commands/nativedisk.c | 1 + - grub-core/disk/nvme-int.h | 208 +++++++++ - grub-core/disk/nvme.c | 781 ++++++++++++++++++++++++++++++++ - include/grub/disk.h | 1 + - 6 files changed, 998 insertions(+), 1 deletion(-) - create mode 100644 grub-core/disk/nvme-int.h - create mode 100644 grub-core/disk/nvme.c - -diff --git a/Makefile.am b/Makefile.am -index 65016f856..7bc0866ba 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -434,7 +434,7 @@ if COND_i386_coreboot - FS_PAYLOAD_MODULES ?= $(shell cat grub-core/fs.lst) - default_payload.elf: grub-mkstandalone grub-mkimage FORCE - test -f $@ && rm $@ || true -- pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata xhci ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg -+ pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata nvme xhci ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg - endif - - endif -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index d3947739f..fb9f24c0f 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2689,3 +2689,9 @@ module = { - cflags = '-Wno-uninitialized'; - cppflags = '-I$(srcdir)/lib/libtasn1-grub -I$(srcdir)/tests/asn1/'; - }; -+ -+module = { -+ name = nvme; -+ common = disk/nvme.c; -+ enable = pci; -+}; -diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c -index 6806bff9c..fd68a513e 100644 ---- a/grub-core/commands/nativedisk.c -+++ b/grub-core/commands/nativedisk.c -@@ -78,6 +78,7 @@ get_uuid (const char *name, char **uuid, int getnative) - case GRUB_DISK_DEVICE_ATA_ID: - case GRUB_DISK_DEVICE_SCSI_ID: - case GRUB_DISK_DEVICE_XEN: -+ case GRUB_DISK_DEVICE_NVME_ID: - if (getnative) - break; - /* FALLTHROUGH */ -diff --git a/grub-core/disk/nvme-int.h b/grub-core/disk/nvme-int.h -new file mode 100644 -index 000000000..1295b58aa ---- /dev/null -+++ b/grub-core/disk/nvme-int.h -@@ -0,0 +1,208 @@ -+// NVMe datastructures and constants -+// -+// Copyright 2017 Amazon.com, Inc. or its affiliates. -+// -+// This file may be distributed under the terms of the GNU LGPLv3 license. -+ -+#ifndef __NVME_INT_H -+#define __NVME_INT_H -+ -+#include <grub/types.h> -+ -+/* Data structures */ -+ -+/* The register file of a NVMe host controller. This struct follows the naming -+ scheme in the NVMe specification. */ -+struct nvme_reg { -+ grub_uint64_t cap; /* controller capabilities */ -+ grub_uint32_t vs; /* version */ -+ grub_uint32_t intms; /* interrupt mask set */ -+ grub_uint32_t intmc; /* interrupt mask clear */ -+ grub_uint32_t cc; /* controller configuration */ -+ grub_uint32_t _res0; -+ grub_uint32_t csts; /* controller status */ -+ grub_uint32_t _res1; -+ grub_uint32_t aqa; /* admin queue attributes */ -+ grub_uint64_t asq; /* admin submission queue base address */ -+ grub_uint64_t acq; /* admin completion queue base address */ -+}; -+ -+/* Submission queue entry */ -+struct nvme_sqe { -+ union { -+ grub_uint32_t dword[16]; -+ struct { -+ grub_uint32_t cdw0; /* Command DWORD 0 */ -+ grub_uint32_t nsid; /* Namespace ID */ -+ grub_uint64_t _res0; -+ grub_uint64_t mptr; /* metadata ptr */ -+ -+ grub_uint64_t dptr_prp1; -+ grub_uint64_t dptr_prp2; -+ }; -+ }; -+}; -+ -+/* Completion queue entry */ -+struct nvme_cqe { -+ union { -+ grub_uint32_t dword[4]; -+ struct { -+ grub_uint32_t cdw0; -+ grub_uint32_t _res0; -+ grub_uint16_t sq_head; -+ grub_uint16_t sq_id; -+ grub_uint16_t cid; -+ grub_uint16_t status; -+ }; -+ }; -+}; -+ -+/* The common part of every submission or completion queue. */ -+struct nvme_queue { -+ grub_uint32_t *dbl; /* doorbell */ -+ grub_uint16_t mask; /* length - 1 */ -+}; -+ -+struct nvme_cq { -+ struct nvme_queue common; -+ struct nvme_cqe *cqe; -+ -+ /* We have read upto (but not including) this entry in the queue. */ -+ grub_uint16_t head; -+ -+ /* The current phase bit the controller uses to indicate that it has written -+ a new entry. This is inverted after each wrap. */ -+ unsigned phase : 1; -+}; -+ -+struct nvme_sq { -+ struct nvme_queue common; -+ struct nvme_sqe *sqe; -+ -+ /* Corresponding completion queue. We only support a single SQ per CQ. */ -+ struct nvme_cq *cq; -+ -+ /* The last entry the controller has fetched. */ -+ grub_uint16_t head; -+ -+ /* The last value we have written to the tail doorbell. */ -+ grub_uint16_t tail; -+}; -+ -+struct nvme_ctrl { -+ grub_pci_device_t pci; -+ struct nvme_reg volatile *reg; -+ -+ grub_uint32_t ctrlnum; -+ -+ grub_uint32_t doorbell_stride; /* in bytes */ -+ -+ struct nvme_sq admin_sq; -+ struct nvme_cq admin_cq; -+ -+ grub_uint32_t ns_count; -+ -+ struct nvme_sq io_sq; -+ struct nvme_cq io_cq; -+}; -+ -+struct nvme_namespace { -+ struct nvme_namespace *next; -+ struct nvme_namespace **prev; -+ -+ char *devname; -+ -+ grub_uint32_t nsnum; -+ -+ struct nvme_ctrl *ctrl; -+ -+ grub_uint32_t ns_id; -+ -+ grub_uint64_t lba_count; /* The total amount of sectors. */ -+ -+ grub_uint32_t block_size; -+ grub_uint32_t metadata_size; -+ grub_uint32_t max_req_size; -+}; -+ -+/* Data structures for NVMe admin identify commands */ -+ -+struct nvme_identify_ctrl { -+ grub_uint16_t vid; -+ grub_uint16_t ssvid; -+ char sn[20]; -+ char mn[40]; -+ char fr[8]; -+ -+ grub_uint8_t rab; -+ grub_uint8_t ieee[3]; -+ grub_uint8_t cmic; -+ grub_uint8_t mdts; -+ -+ char _boring[516 - 78]; -+ -+ grub_uint32_t nn; /* number of namespaces */ -+}; -+ -+struct nvme_identify_ns_list { -+ grub_uint32_t ns_id[1024]; -+}; -+ -+struct nvme_lba_format { -+ grub_uint16_t ms; -+ grub_uint8_t lbads; -+ grub_uint8_t rp; -+}; -+ -+struct nvme_identify_ns { -+ grub_uint64_t nsze; -+ grub_uint64_t ncap; -+ grub_uint64_t nuse; -+ grub_uint8_t nsfeat; -+ grub_uint8_t nlbaf; -+ grub_uint8_t flbas; -+ -+ char _boring[128 - 27]; -+ -+ struct nvme_lba_format lbaf[16]; -+}; -+ -+union nvme_identify { -+ struct nvme_identify_ns ns; -+ struct nvme_identify_ctrl ctrl; -+ struct nvme_identify_ns_list ns_list; -+}; -+ -+/* NVMe constants */ -+ -+#define NVME_CAP_CSS_NVME (1ULL << 37) -+ -+#define NVME_CSTS_FATAL (1U << 1) -+#define NVME_CSTS_RDY (1U << 0) -+ -+#define NVME_CC_EN (1U << 0) -+ -+#define NVME_SQE_OPC_ADMIN_CREATE_IO_SQ 1U -+#define NVME_SQE_OPC_ADMIN_CREATE_IO_CQ 5U -+#define NVME_SQE_OPC_ADMIN_IDENTIFY 6U -+ -+#define NVME_SQE_OPC_IO_WRITE 1U -+#define NVME_SQE_OPC_IO_READ 2U -+ -+#define NVME_ADMIN_IDENTIFY_CNS_ID_NS 0U -+#define NVME_ADMIN_IDENTIFY_CNS_ID_CTRL 1U -+#define NVME_ADMIN_IDENTIFY_CNS_GET_NS_LIST 2U -+ -+#define NVME_CQE_DW3_P (1U << 16) -+ -+#define NVME_PAGE_SIZE 4096 -+#define NVME_PAGE_MASK ~(NVME_PAGE_SIZE - 1) -+ -+/* Length for the queue entries. */ -+#define NVME_SQE_SIZE_LOG 6 -+#define NVME_CQE_SIZE_LOG 4 -+ -+#endif -+ -+/* EOF */ -diff --git a/grub-core/disk/nvme.c b/grub-core/disk/nvme.c -new file mode 100644 -index 000000000..093237c70 ---- /dev/null -+++ b/grub-core/disk/nvme.c -@@ -0,0 +1,781 @@ -+// Low level NVMe disk access -+// -+// Based on SeaBIOS NVMe driver - Copyright 2017 Amazon.com, Inc. or its affiliates. -+// Port to GRUB2 done by Mate Kukri -+// -+// This file may be distributed under the terms of the GNU LGPLv3 license. -+ -+#include <grub/disk.h> -+#include <grub/dl.h> -+#include <grub/pci.h> -+#include "nvme-int.h" -+ -+GRUB_MOD_LICENSE ("GPLv3"); /* LGPLv3 in reality but it is GPLv3 compatible */ -+ -+static grub_uint32_t grub_nvme_ctrlcnt; -+static grub_uint32_t grub_nvme_nscnt; -+ -+static struct nvme_namespace *grub_nvme_namespaces; -+ -+// Page aligned "dma bounce buffer" of size NVME_PAGE_SIZE -+static void *nvme_dma_buffer; -+ -+static void * -+zalloc_page_aligned(grub_uint32_t size) -+{ -+ void *res = grub_memalign(NVME_PAGE_SIZE, size); -+ if (res) grub_memset(res, 0, size); -+ return res; -+} -+ -+static void -+nvme_init_queue_common(struct nvme_ctrl *ctrl, struct nvme_queue *q, grub_uint16_t q_idx, -+ grub_uint16_t length) -+{ -+ grub_memset(q, 0, sizeof(*q)); -+ q->dbl = (grub_uint32_t *)((char *)ctrl->reg + 0x1000 + q_idx * ctrl->doorbell_stride); -+ grub_dprintf("nvme", " q %p q_idx %u dbl %p\n", q, q_idx, q->dbl); -+ q->mask = length - 1; -+} -+ -+static int -+nvme_init_sq(struct nvme_ctrl *ctrl, struct nvme_sq *sq, grub_uint16_t q_idx, grub_uint16_t length, -+ struct nvme_cq *cq) -+{ -+ nvme_init_queue_common(ctrl, &sq->common, q_idx, length); -+ sq->sqe = zalloc_page_aligned(sizeof(*sq->sqe) * length); -+ -+ if (!sq->sqe) { -+ return -1; -+ } -+ -+ grub_dprintf("nvme", "sq %p q_idx %u sqe %p\n", sq, q_idx, sq->sqe); -+ sq->cq = cq; -+ sq->head = 0; -+ sq->tail = 0; -+ -+ return 0; -+} -+ -+static int -+nvme_init_cq(struct nvme_ctrl *ctrl, struct nvme_cq *cq, grub_uint16_t q_idx, grub_uint16_t length) -+{ -+ nvme_init_queue_common(ctrl, &cq->common, q_idx, length); -+ cq->cqe = zalloc_page_aligned(sizeof(*cq->cqe) * length); -+ if (!cq->cqe) { -+ return -1; -+ } -+ -+ cq->head = 0; -+ -+ /* All CQE phase bits are initialized to zero. This means initially we wait -+ for the host controller to set these to 1. */ -+ cq->phase = 1; -+ -+ return 0; -+} -+ -+static int -+nvme_poll_cq(struct nvme_cq *cq) -+{ -+ grub_uint32_t dw3 = *(volatile grub_uint32_t *) &cq->cqe[cq->head].dword[3]; -+ return (!!(dw3 & NVME_CQE_DW3_P) == cq->phase); -+} -+ -+static int -+nvme_is_cqe_success(struct nvme_cqe const *cqe) -+{ -+ return ((cqe->status >> 1) & 0xFF) == 0; -+} -+ -+static struct nvme_cqe -+nvme_error_cqe(void) -+{ -+ struct nvme_cqe r; -+ -+ /* 0xFF is a vendor specific status code != success. Should be okay for -+ indicating failure. */ -+ grub_memset(&r, 0xFF, sizeof(r)); -+ return r; -+} -+ -+static struct nvme_cqe -+nvme_consume_cqe(struct nvme_sq *sq) -+{ -+ struct nvme_cq *cq = sq->cq; -+ -+ if (!nvme_poll_cq(cq)) { -+ /* Cannot consume a completion queue entry, if there is none ready. */ -+ return nvme_error_cqe(); -+ } -+ -+ struct nvme_cqe *cqe = &cq->cqe[cq->head]; -+ grub_uint16_t cq_next_head = (cq->head + 1) & cq->common.mask; -+ grub_dprintf("nvme", "cq %p head %u -> %u\n", cq, cq->head, cq_next_head); -+ if (cq_next_head < cq->head) { -+ grub_dprintf("nvme", "cq %p wrap\n", cq); -+ cq->phase = ~cq->phase; -+ } -+ cq->head = cq_next_head; -+ -+ /* Update the submission queue head. */ -+ if (cqe->sq_head != sq->head) { -+ sq->head = cqe->sq_head; -+ grub_dprintf("nvme", "sq %p advanced to %u\n", sq, cqe->sq_head); -+ } -+ -+ /* Tell the controller that we consumed the completion. */ -+ *(volatile grub_uint32_t *) cq->common.dbl = cq->head; -+ -+ return *cqe; -+} -+ -+static struct nvme_cqe -+nvme_wait(struct nvme_sq *sq) -+{ -+ // static const unsigned nvme_timeout = 5000 /* ms */; -+ // grub_uint32_t to = timer_calc(nvme_timeout); -+ while (!nvme_poll_cq(sq->cq)) { -+ /* FIXME -+ yield(); -+ -+ if (timer_check(to)) { -+ warn_timeout(); -+ return nvme_error_cqe(); -+ }*/ -+ } -+ -+ return nvme_consume_cqe(sq); -+} -+ -+/* Returns the next submission queue entry (or NULL if the queue is full). It -+ also fills out Command Dword 0 and clears the rest. */ -+static struct nvme_sqe * -+nvme_get_next_sqe(struct nvme_sq *sq, grub_uint8_t opc, void *metadata, void *data, void *data2) -+{ -+ if (((sq->head + 1) & sq->common.mask) == sq->tail) { -+ grub_dprintf("nvme", "submission queue is full\n"); -+ return NULL; -+ } -+ -+ struct nvme_sqe *sqe = &sq->sqe[sq->tail]; -+ grub_dprintf("nvme", "sq %p next_sqe %u\n", sq, sq->tail); -+ -+ grub_memset(sqe, 0, sizeof(*sqe)); -+ sqe->cdw0 = opc | (sq->tail << 16 /* CID */); -+ sqe->mptr = (grub_uint32_t)metadata; -+ sqe->dptr_prp1 = (grub_uint32_t)data; -+ sqe->dptr_prp2 = (grub_uint32_t)data2; -+ -+ return sqe; -+} -+ -+/* Call this after you've filled out an sqe that you've got from nvme_get_next_sqe. */ -+static void -+nvme_commit_sqe(struct nvme_sq *sq) -+{ -+ grub_dprintf("nvme", "sq %p commit_sqe %u\n", sq, sq->tail); -+ sq->tail = (sq->tail + 1) & sq->common.mask; -+ *(volatile grub_uint32_t *) sq->common.dbl = sq->tail; -+} -+ -+/* Perform an identify command on the admin queue and return the resulting -+ buffer. This may be a NULL pointer, if something failed. This function -+ cannot be used after initialization, because it uses buffers in tmp zone. */ -+static union nvme_identify * -+nvme_admin_identify(struct nvme_ctrl *ctrl, grub_uint8_t cns, grub_uint32_t nsid) -+{ -+ union nvme_identify *identify_buf = zalloc_page_aligned(4096); -+ if (!identify_buf) -+ return NULL; -+ -+ struct nvme_sqe *cmd_identify; -+ cmd_identify = nvme_get_next_sqe(&ctrl->admin_sq, -+ NVME_SQE_OPC_ADMIN_IDENTIFY, NULL, -+ identify_buf, NULL); -+ if (!cmd_identify) -+ goto error; -+ -+ cmd_identify->nsid = nsid; -+ cmd_identify->dword[10] = cns; -+ -+ nvme_commit_sqe(&ctrl->admin_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ctrl->admin_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ goto error; -+ } -+ -+ return identify_buf; -+ error: -+ grub_free(identify_buf); -+ return NULL; -+} -+ -+static struct nvme_identify_ctrl * -+nvme_admin_identify_ctrl(struct nvme_ctrl *ctrl) -+{ -+ return &nvme_admin_identify(ctrl, NVME_ADMIN_IDENTIFY_CNS_ID_CTRL, 0)->ctrl; -+} -+ -+static struct nvme_identify_ns * -+nvme_admin_identify_ns(struct nvme_ctrl *ctrl, grub_uint32_t ns_id) -+{ -+ return &nvme_admin_identify(ctrl, NVME_ADMIN_IDENTIFY_CNS_ID_NS, -+ ns_id)->ns; -+} -+ -+static void -+nvme_probe_ns(struct nvme_ctrl *ctrl, grub_uint32_t ns_idx, grub_uint8_t mdts) -+{ -+ grub_uint32_t ns_id = ns_idx + 1; -+ -+ struct nvme_identify_ns *id = nvme_admin_identify_ns(ctrl, ns_id); -+ if (!id) { -+ grub_dprintf("nvme", "NVMe couldn't identify namespace %u.\n", ns_id); -+ goto free_buffer; -+ } -+ -+ grub_uint8_t current_lba_format = id->flbas & 0xF; -+ if (current_lba_format > id->nlbaf) { -+ grub_dprintf("nvme", "NVMe NS %u: current LBA format %u is beyond what the " -+ " namespace supports (%u)?\n", -+ ns_id, current_lba_format, id->nlbaf + 1); -+ goto free_buffer; -+ } -+ -+ if (!id->nsze) { -+ grub_dprintf("nvme", "NVMe NS %u is inactive.\n", ns_id); -+ goto free_buffer; -+ } -+ -+ if (!nvme_dma_buffer) { -+ nvme_dma_buffer = zalloc_page_aligned(NVME_PAGE_SIZE); -+ if (!nvme_dma_buffer) { -+ goto free_buffer; -+ } -+ } -+ -+ struct nvme_namespace *ns = grub_malloc(sizeof(*ns)); -+ if (!ns) { -+ goto free_buffer; -+ } -+ grub_memset(ns, 0, sizeof(*ns)); -+ ns->ctrl = ctrl; -+ ns->ns_id = ns_id; -+ ns->lba_count = id->nsze; -+ -+ struct nvme_lba_format *fmt = &id->lbaf[current_lba_format]; -+ -+ ns->block_size = 1U << fmt->lbads; -+ ns->metadata_size = fmt->ms; -+ -+ if (ns->block_size > NVME_PAGE_SIZE) { -+ /* If we see devices that trigger this path, we need to increase our -+ buffer size. */ -+ grub_free(ns); -+ goto free_buffer; -+ } -+ -+ if (mdts) { -+ ns->max_req_size = ((1U << mdts) * NVME_PAGE_SIZE) / ns->block_size; -+ grub_dprintf("nvme", "NVME NS %u max request size: %d sectors\n", -+ ns_id, ns->max_req_size); -+ } else { -+ ns->max_req_size = -1U; -+ } -+ -+ ns->devname = grub_xasprintf("nvme%un%u", ctrl->ctrlnum, ns_id); -+ ns->nsnum = grub_nvme_nscnt++; -+ -+ grub_list_push (GRUB_AS_LIST_P (&grub_nvme_namespaces), GRUB_AS_LIST (ns)); -+ -+free_buffer: -+ grub_free(id); -+} -+ -+ -+/* Release memory allocated for a completion queue */ -+static void -+nvme_destroy_cq(struct nvme_cq *cq) -+{ -+ grub_free(cq->cqe); -+ cq->cqe = NULL; -+} -+ -+/* Release memory allocated for a submission queue */ -+static void -+nvme_destroy_sq(struct nvme_sq *sq) -+{ -+ grub_free(sq->sqe); -+ sq->sqe = NULL; -+} -+ -+/* Returns 0 on success. */ -+static int -+nvme_create_io_cq(struct nvme_ctrl *ctrl, struct nvme_cq *cq, grub_uint16_t q_idx) -+{ -+ int rc; -+ struct nvme_sqe *cmd_create_cq; -+ grub_uint32_t length = 1 + (ctrl->reg->cap & 0xffff); -+ if (length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe)) -+ length = NVME_PAGE_SIZE / sizeof(struct nvme_cqe); -+ -+ rc = nvme_init_cq(ctrl, cq, q_idx, length); -+ if (rc) { -+ goto err; -+ } -+ -+ cmd_create_cq = nvme_get_next_sqe(&ctrl->admin_sq, -+ NVME_SQE_OPC_ADMIN_CREATE_IO_CQ, NULL, -+ cq->cqe, NULL); -+ if (!cmd_create_cq) { -+ goto err_destroy_cq; -+ } -+ -+ cmd_create_cq->dword[10] = (cq->common.mask << 16) | (q_idx >> 1); -+ cmd_create_cq->dword[11] = 1 /* physically contiguous */; -+ -+ nvme_commit_sqe(&ctrl->admin_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ctrl->admin_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ grub_dprintf("nvme", "create io cq failed: %08x %08x %08x %08x\n", -+ cqe.dword[0], cqe.dword[1], cqe.dword[2], cqe.dword[3]); -+ -+ goto err_destroy_cq; -+ } -+ -+ return 0; -+ -+err_destroy_cq: -+ nvme_destroy_cq(cq); -+err: -+ return -1; -+} -+ -+/* Returns 0 on success. */ -+static int -+nvme_create_io_sq(struct nvme_ctrl *ctrl, struct nvme_sq *sq, grub_uint16_t q_idx, struct nvme_cq *cq) -+{ -+ int rc; -+ struct nvme_sqe *cmd_create_sq; -+ grub_uint32_t length = 1 + (ctrl->reg->cap & 0xffff); -+ if (length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe)) -+ length = NVME_PAGE_SIZE / sizeof(struct nvme_cqe); -+ -+ rc = nvme_init_sq(ctrl, sq, q_idx, length, cq); -+ if (rc) { -+ goto err; -+ } -+ -+ cmd_create_sq = nvme_get_next_sqe(&ctrl->admin_sq, -+ NVME_SQE_OPC_ADMIN_CREATE_IO_SQ, NULL, -+ sq->sqe, NULL); -+ if (!cmd_create_sq) { -+ goto err_destroy_sq; -+ } -+ -+ cmd_create_sq->dword[10] = (sq->common.mask << 16) | (q_idx >> 1); -+ cmd_create_sq->dword[11] = (q_idx >> 1) << 16 | 1 /* contiguous */; -+ grub_dprintf("nvme", "sq %p create dword10 %08x dword11 %08x\n", sq, -+ cmd_create_sq->dword[10], cmd_create_sq->dword[11]); -+ -+ nvme_commit_sqe(&ctrl->admin_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ctrl->admin_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ grub_dprintf("nvme", "create io sq failed: %08x %08x %08x %08x\n", -+ cqe.dword[0], cqe.dword[1], cqe.dword[2], cqe.dword[3]); -+ goto err_destroy_sq; -+ } -+ -+ return 0; -+ -+err_destroy_sq: -+ nvme_destroy_sq(sq); -+err: -+ return -1; -+} -+ -+/* Reads count sectors into buf. The buffer cannot cross page boundaries. */ -+static int -+nvme_io_xfer(struct nvme_namespace *ns, grub_uint64_t lba, void *prp1, void *prp2, -+ grub_uint16_t count, int write) -+{ -+ if (((grub_uint32_t)prp1 & 0x3) || ((grub_uint32_t)prp2 & 0x3)) { -+ /* Buffer is misaligned */ -+ return -1; -+ } -+ -+ struct nvme_sqe *io_read = nvme_get_next_sqe(&ns->ctrl->io_sq, -+ write ? NVME_SQE_OPC_IO_WRITE -+ : NVME_SQE_OPC_IO_READ, -+ NULL, prp1, prp2); -+ io_read->nsid = ns->ns_id; -+ io_read->dword[10] = (grub_uint32_t)lba; -+ io_read->dword[11] = (grub_uint32_t)(lba >> 32); -+ io_read->dword[12] = (1U << 31 /* limited retry */) | (count - 1); -+ -+ nvme_commit_sqe(&ns->ctrl->io_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ns->ctrl->io_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ grub_dprintf("nvme", "read io: %08x %08x %08x %08x\n", -+ cqe.dword[0], cqe.dword[1], cqe.dword[2], cqe.dword[3]); -+ -+ return -1; -+ } -+ -+ grub_dprintf("nvme", "ns %u %s lba %llu+%u\n", ns->ns_id, write ? "write" : "read", -+ lba, count); -+ return count; -+} -+ -+// Transfer up to one page of data using the internal dma bounce buffer -+static int -+nvme_bounce_xfer(struct nvme_namespace *ns, grub_uint64_t lba, void *buf, grub_uint16_t count, -+ int write) -+{ -+ grub_uint16_t const max_blocks = NVME_PAGE_SIZE / ns->block_size; -+ grub_uint16_t blocks = count < max_blocks ? count : max_blocks; -+ -+ if (write) -+ grub_memcpy(nvme_dma_buffer, buf, blocks * ns->block_size); -+ -+ int res = nvme_io_xfer(ns, lba, nvme_dma_buffer, NULL, blocks, write); -+ -+ if (!write && res >= 0) -+ grub_memcpy(buf, nvme_dma_buffer, res * ns->block_size); -+ -+ return res; -+} -+ -+#define NVME_MAX_PRPL_ENTRIES 15 /* Allows requests up to 64kb */ -+ -+// Transfer data using page list (if applicable) -+static int -+nvme_prpl_xfer(struct nvme_namespace *ns, grub_uint64_t lba, void *buf, grub_uint16_t count, -+ int write) -+{ -+ grub_uint32_t base = (long)buf; -+ grub_int32_t size; -+ -+ if (count > ns->max_req_size) -+ count = ns->max_req_size; -+ -+ size = count * ns->block_size; -+ /* Special case for transfers that fit into PRP1, but are unaligned */ -+ if (((size + (base & ~NVME_PAGE_MASK)) <= NVME_PAGE_SIZE)) -+ goto single; -+ -+ /* Every request has to be page aligned */ -+ if (base & ~NVME_PAGE_MASK) -+ goto bounce; -+ -+ /* Make sure a full block fits into the last chunk */ -+ if (size & (ns->block_size - 1ULL)) -+ goto bounce; -+ -+ /* Build PRP list if we need to describe more than 2 pages */ -+ if ((ns->block_size * count) > (NVME_PAGE_SIZE * 2)) { -+ grub_uint32_t prpl_len = 0; -+ grub_uint64_t *prpl = nvme_dma_buffer; -+ int first_page = 1; -+ for (; size > 0; base += NVME_PAGE_SIZE, size -= NVME_PAGE_SIZE) { -+ if (first_page) { -+ /* First page is special */ -+ first_page = 0; -+ continue; -+ } -+ if (prpl_len >= NVME_MAX_PRPL_ENTRIES) -+ goto bounce; -+ prpl[prpl_len++] = base; -+ } -+ return nvme_io_xfer(ns, lba, buf, prpl, count, write); -+ } -+ -+ /* Directly embed the 2nd page if we only need 2 pages */ -+ if ((ns->block_size * count) > NVME_PAGE_SIZE) -+ return nvme_io_xfer(ns, lba, buf, (char *) buf + NVME_PAGE_SIZE, count, write); -+ -+single: -+ /* One page is enough, don't expose anything else */ -+ return nvme_io_xfer(ns, lba, buf, NULL, count, write); -+ -+bounce: -+ /* Use bounce buffer to make transfer */ -+ return nvme_bounce_xfer(ns, lba, buf, count, write); -+} -+ -+static int -+nvme_create_io_queues(struct nvme_ctrl *ctrl) -+{ -+ if (nvme_create_io_cq(ctrl, &ctrl->io_cq, 3)) -+ goto err; -+ -+ if (nvme_create_io_sq(ctrl, &ctrl->io_sq, 2, &ctrl->io_cq)) -+ goto err_free_cq; -+ -+ return 0; -+ -+ err_free_cq: -+ nvme_destroy_cq(&ctrl->io_cq); -+ err: -+ return -1; -+} -+ -+/* Waits for CSTS.RDY to match rdy. Returns 0 on success. */ -+static int -+nvme_wait_csts_rdy(struct nvme_ctrl *ctrl, unsigned rdy) -+{ -+ // grub_uint32_t const max_to = 500 /* ms */ * ((ctrl->reg->cap >> 24) & 0xFFU); -+ // grub_uint32_t to = timer_calc(max_to); -+ grub_uint32_t csts; -+ -+ while (rdy != ((csts = ctrl->reg->csts) & NVME_CSTS_RDY)) { -+ // FIXME -+ //yield(); -+ -+ if (csts & NVME_CSTS_FATAL) { -+ grub_dprintf("nvme", "NVMe fatal error during controller shutdown\n"); -+ return -1; -+ } -+ -+ /* -+ if (timer_check(to)) { -+ warn_timeout(); -+ return -1; -+ }*/ -+ } -+ -+ return 0; -+} -+ -+/* Returns 0 on success. */ -+static int grub_nvme_controller_enable(struct nvme_ctrl *ctrl) -+{ -+ grub_pci_address_t addr; -+ int rc; -+ -+ addr = grub_pci_make_address (ctrl->pci, GRUB_PCI_REG_COMMAND); -+ grub_pci_write_word (addr, grub_pci_read_word (addr) | GRUB_PCI_COMMAND_BUS_MASTER); -+ -+ /* Turn the controller off. */ -+ ctrl->reg->cc = 0; -+ if (nvme_wait_csts_rdy(ctrl, 0)) { -+ grub_dprintf("nvme", "NVMe fatal error during controller shutdown\n"); -+ return -1; -+ } -+ -+ ctrl->doorbell_stride = 4U << ((ctrl->reg->cap >> 32) & 0xF); -+ -+ rc = nvme_init_cq(ctrl, &ctrl->admin_cq, 1, -+ NVME_PAGE_SIZE / sizeof(struct nvme_cqe)); -+ if (rc) { -+ return -1; -+ } -+ -+ rc = nvme_init_sq(ctrl, &ctrl->admin_sq, 0, -+ NVME_PAGE_SIZE / sizeof(struct nvme_sqe), &ctrl->admin_cq); -+ if (rc) { -+ goto err_destroy_admin_cq; -+ } -+ -+ ctrl->reg->aqa = ctrl->admin_cq.common.mask << 16 -+ | ctrl->admin_sq.common.mask; -+ -+ ctrl->reg->asq = (grub_uint32_t)ctrl->admin_sq.sqe; -+ ctrl->reg->acq = (grub_uint32_t)ctrl->admin_cq.cqe; -+ -+ grub_dprintf("nvme", " admin submission queue: %p\n", ctrl->admin_sq.sqe); -+ grub_dprintf("nvme", " admin completion queue: %p\n", ctrl->admin_cq.cqe); -+ -+ ctrl->reg->cc = NVME_CC_EN | (NVME_CQE_SIZE_LOG << 20) -+ | (NVME_SQE_SIZE_LOG << 16 /* IOSQES */); -+ -+ if (nvme_wait_csts_rdy(ctrl, 1)) { -+ grub_dprintf("nvme", "NVMe fatal error while enabling controller\n"); -+ goto err_destroy_admin_sq; -+ } -+ -+ /* The admin queue is set up and the controller is ready. Let's figure out -+ what namespaces we have. */ -+ -+ struct nvme_identify_ctrl *identify = nvme_admin_identify_ctrl(ctrl); -+ -+ if (!identify) { -+ grub_dprintf("nvme", "NVMe couldn't identify controller.\n"); -+ goto err_destroy_admin_sq; -+ } -+ -+ grub_dprintf("nvme", "NVMe has %u namespace%s.\n", -+ identify->nn, (identify->nn == 1) ? "" : "s"); -+ -+ ctrl->ns_count = identify->nn; -+ grub_uint8_t mdts = identify->mdts; -+ grub_free(identify); -+ -+ if ((ctrl->ns_count == 0) || nvme_create_io_queues(ctrl)) { -+ /* No point to continue, if the controller says it doesn't have -+ namespaces or we couldn't create I/O queues. */ -+ goto err_destroy_admin_sq; -+ } -+ -+ /* Give the controller a global number */ -+ ctrl->ctrlnum = grub_nvme_ctrlcnt++; -+ -+ /* Populate namespace IDs */ -+ for (grub_uint32_t ns_idx = 0; ns_idx < ctrl->ns_count; ns_idx++) { -+ nvme_probe_ns(ctrl, ns_idx, mdts); -+ } -+ -+ grub_dprintf("nvme", "NVMe initialization complete!\n"); -+ return 0; -+ -+ err_destroy_admin_sq: -+ nvme_destroy_sq(&ctrl->admin_sq); -+ err_destroy_admin_cq: -+ nvme_destroy_cq(&ctrl->admin_cq); -+ return -1; -+} -+ -+static int grub_nvme_pci_probe(grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)), void *data __attribute__ ((unused))) -+{ -+ grub_pci_address_t addr; -+ grub_uint32_t class, bar, version; -+ struct nvme_reg volatile *reg; -+ -+ class = grub_pci_read (grub_pci_make_address (dev, GRUB_PCI_REG_CLASS)); -+ if (class >> 16 != 0x0108) -+ return 0; -+ if ((class >> 8 & 0xff) != 2) { /* as of NVM 1.0e */ -+ grub_dprintf("nvme", "Found incompatble NVMe: prog-if=%02x\n", class >> 8 & 0xff); -+ return 0; -+ } -+ -+ bar = grub_pci_read (grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0)); -+ reg = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, sizeof (*reg)); -+ -+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); -+ grub_pci_write_word (addr, grub_pci_read_word (addr) | GRUB_PCI_COMMAND_MEM_ENABLED); -+ -+ version = reg->vs; -+ grub_dprintf("nvme", "Found NVMe controller with version %u.%u.%u.\n", version >> 16, (version >> 8) & 0xFF, version & 0xFF); -+ grub_dprintf("nvme", " Capabilities %016llx\n", reg->cap); -+ -+ if (~reg->cap & NVME_CAP_CSS_NVME) { -+ grub_dprintf("nvme", "Controller doesn't speak NVMe command set. Skipping.\n"); -+ goto err; -+ } -+ -+ struct nvme_ctrl *ctrl = grub_malloc(sizeof(*ctrl)); -+ if (!ctrl) -+ goto err; -+ -+ grub_memset(ctrl, 0, sizeof(*ctrl)); -+ -+ ctrl->reg = reg; -+ ctrl->pci = dev; -+ -+ if (grub_nvme_controller_enable(ctrl)) -+ goto err_free_ctrl; -+ -+ return 0; -+ -+ err_free_ctrl: -+ grub_free(ctrl); -+ err: -+ grub_dprintf("nvme", "Failed to enable NVMe controller.\n"); -+ return 0; -+} -+ -+static int -+grub_nvme_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) -+{ -+ struct nvme_namespace *ns; -+ -+ if (pull != GRUB_DISK_PULL_NONE) -+ return 0; -+ -+ FOR_LIST_ELEMENTS(ns, grub_nvme_namespaces) -+ if (hook (ns->devname, hook_data)) -+ return 1; -+ -+ return 0; -+} -+ -+static grub_err_t -+grub_nvme_open (const char *name __attribute ((unused)), grub_disk_t disk __attribute ((unused))) -+{ -+ struct nvme_namespace *ns; -+ -+ FOR_LIST_ELEMENTS(ns, grub_nvme_namespaces) -+ if (grub_strcmp (ns->devname, name) == 0) -+ break; -+ -+ if (! ns) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); -+ -+ disk->total_sectors = ns->lba_count; -+ disk->max_agglomerate = ns->max_req_size; -+ -+ disk->id = ns->nsnum; /* global id of the namespace */ -+ -+ disk->data = ns; -+ -+ return 0; -+} -+ -+static grub_err_t -+nvme_readwrite(struct nvme_namespace *ns, grub_disk_addr_t sector, grub_size_t num_sectors, char *buf, int write) -+{ -+ for (int i = 0; i < num_sectors;) { -+ grub_uint16_t blocks_remaining = num_sectors - i; -+ char *op_buf = buf + i * ns->block_size; -+ int blocks = nvme_prpl_xfer(ns, sector + i, op_buf, blocks_remaining, write); -+ if (blocks < 0) -+ return GRUB_ERR_IO; -+ i += blocks; -+ } -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_nvme_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t num_sectors, char *buf) -+{ -+ return nvme_readwrite((struct nvme_namespace *) disk->data, sector, num_sectors, buf, 0); -+} -+ -+static grub_err_t -+grub_nvme_write (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t num_sectors, const char *buf) -+{ -+ return nvme_readwrite((struct nvme_namespace *) disk->data, sector, num_sectors, buf, 1); -+} -+ -+static struct grub_disk_dev grub_nvme_dev = -+ { -+ .name = "nvme", -+ .id = GRUB_DISK_DEVICE_NVME_ID, -+ .disk_iterate = grub_nvme_iterate, -+ .disk_open = grub_nvme_open, -+ .disk_read = grub_nvme_read, -+ .disk_write = grub_nvme_write, -+ .next = 0 -+ }; -+ -+GRUB_MOD_INIT(nvme) -+{ -+ grub_stop_disk_firmware (); -+ grub_pci_iterate (grub_nvme_pci_probe, NULL); -+ grub_disk_dev_register (&grub_nvme_dev); -+} -+ -+GRUB_MOD_FINI(nvme) -+{ -+ grub_disk_dev_unregister (&grub_nvme_dev); -+} -diff --git a/include/grub/disk.h b/include/grub/disk.h -index fbf23df7f..186e76f0b 100644 ---- a/include/grub/disk.h -+++ b/include/grub/disk.h -@@ -52,6 +52,7 @@ enum grub_disk_dev_id - GRUB_DISK_DEVICE_UBOOTDISK_ID, - GRUB_DISK_DEVICE_XEN, - GRUB_DISK_DEVICE_OBDISK_ID, -+ GRUB_DISK_DEVICE_NVME_ID - }; - - struct grub_disk; --- -2.39.5 - diff --git a/config/grub/xhci/patches/0026-kern-coreboot-mmap-Map-to-reserved.patch b/config/grub/xhci/patches/0026-kern-coreboot-mmap-Map-to-reserved.patch deleted file mode 100644 index 712d2218..00000000 --- a/config/grub/xhci/patches/0026-kern-coreboot-mmap-Map-to-reserved.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d73ca74ef879bf602274bee6eb24f0080a45d235 Mon Sep 17 00:00:00 2001 -From: Paul Menzel <pmenzel@molgen.mpg.de> -Date: Mon, 17 May 2021 10:24:36 +0200 -Subject: [PATCH 26/26] kern/coreboot/mmap: Map to reserved - -https://git.savannah.gnu.org/cgit/grub.git/commit/?id=6de9ee86bf9ae50967413e6a73b5dfd13e5ffb50 - -Signed-off-by: Paul Menzel <pmenzel@molgen.mpg.de> ---- - grub-core/kern/coreboot/mmap.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/grub-core/kern/coreboot/mmap.c b/grub-core/kern/coreboot/mmap.c -index caf8f7cef..2fc316e8d 100644 ---- a/grub-core/kern/coreboot/mmap.c -+++ b/grub-core/kern/coreboot/mmap.c -@@ -59,7 +59,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data) - /* Multiboot mmaps match with the coreboot mmap - definition. Therefore, we can just pass type - through. */ -- mem_region->type, -+ (mem_region->type >= 13) ? 2 : mem_region->type, - ctx->hook_data)) - return 1; - if (start < 0xa0000) -@@ -81,7 +81,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data) - /* Multiboot mmaps match with the coreboot mmap - definition. Therefore, we can just pass type - through. */ -- mem_region->type, -+ (mem_region->type >= 13) ? 2 : mem_region->type, - ctx->hook_data)) - return 1; - } --- -2.39.5 - diff --git a/config/grub/xhci/target.cfg b/config/grub/xhci/target.cfg deleted file mode 100644 index df3e605e..00000000 --- a/config/grub/xhci/target.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -tree="xhci" -rev="a68a7dece464c35b1c8d20b98502b6881b103911" |