diff options
Diffstat (limited to 'config/grub/xhci/patches')
22 files changed, 0 insertions, 7896 deletions
| diff --git a/config/grub/xhci/patches/0001-borderfix/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch b/config/grub/xhci/patches/0001-borderfix/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch deleted file mode 100644 index 183f5a91..00000000 --- a/config/grub/xhci/patches/0001-borderfix/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch +++ /dev/null @@ -1,90 +0,0 @@ -From ce13539fe2103abbd991814d995e06cf96e485f7 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 31 Oct 2021 03:47:05 +0000 -Subject: [PATCH 1/3] 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 b1321eb26..e76094dfd 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, -@@ -410,8 +367,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.25.1 - diff --git a/config/grub/xhci/patches/0001-borderfix/0002-say-the-name-libreboot-in-the-grub-menu.patch b/config/grub/xhci/patches/0001-borderfix/0002-say-the-name-libreboot-in-the-grub-menu.patch deleted file mode 100644 index 6ff97979..00000000 --- a/config/grub/xhci/patches/0001-borderfix/0002-say-the-name-libreboot-in-the-grub-menu.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 70f9e72c3ff6381fe3519612de3b649c0cf26b9a Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sat, 19 Nov 2022 16:30:24 +0000 -Subject: [PATCH 2/3] 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 bd4431000..31308e16a 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 20240504 release, based on coreboot.    https://libreboot.org/")); -   if (!msg_formatted) -     return; -  ---  -2.25.1 - diff --git a/config/grub/xhci/patches/0002-luks2/0003-Add-CC0-license.patch b/config/grub/xhci/patches/0002-luks2/0003-Add-CC0-license.patch deleted file mode 100644 index dc9060c3..00000000 --- a/config/grub/xhci/patches/0002-luks2/0003-Add-CC0-license.patch +++ /dev/null @@ -1,42 +0,0 @@ -From de6e7cc62522ce1be21bd2f06e7c15cd234b5426 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 1/6] 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 0bf40caa6..4011e2d15 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -470,7 +470,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.2 - diff --git a/config/grub/xhci/patches/0002-luks2/0004-Define-GRUB_UINT32_MAX.patch b/config/grub/xhci/patches/0002-luks2/0004-Define-GRUB_UINT32_MAX.patch deleted file mode 100644 index be875e67..00000000 --- a/config/grub/xhci/patches/0002-luks2/0004-Define-GRUB_UINT32_MAX.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 9edaaffac91d593a439e44bac3b6f5558f5a8245 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 2/6] 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 0d96006fe..a13f3a60b 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.2 - diff --git a/config/grub/xhci/patches/0002-luks2/0005-Add-Argon2-algorithm.patch b/config/grub/xhci/patches/0002-luks2/0005-Add-Argon2-algorithm.patch deleted file mode 100644 index 1c6b4f04..00000000 --- a/config/grub/xhci/patches/0002-luks2/0005-Add-Argon2-algorithm.patch +++ /dev/null @@ -1,2611 +0,0 @@ -From 5b63da5c4267933f573ca37ce39a073098c443ba Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 3/6] 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 a695b02f0..313335a53 100644 ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -503,11 +503,75 @@ GRUB includes some code from other projects, and it is sometimes necessary - to update it. -  - @menu -+* Argon2:: - * Gnulib:: - * jsmn:: - * minilzo:: - @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 d2cf29584..4a06789e5 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1215,6 +1215,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.2 - diff --git a/config/grub/xhci/patches/0002-luks2/0006-Error-on-missing-Argon2id-parameters.patch b/config/grub/xhci/patches/0002-luks2/0006-Error-on-missing-Argon2id-parameters.patch deleted file mode 100644 index 5d56bd61..00000000 --- a/config/grub/xhci/patches/0002-luks2/0006-Error-on-missing-Argon2id-parameters.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0044d32121bf52c4547c6b3c78f12d7305f57e6b Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 4/6] 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 d5106402f..bc818ea69 100644 ---- a/grub-core/disk/luks2.c -+++ b/grub-core/disk/luks2.c -@@ -38,6 +38,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; -@@ -90,7 +91,7 @@ struct grub_luks2_keyslot - 	grub_int64_t time; - 	grub_int64_t memory; - 	grub_int64_t cpus; --      } argon2i; -+      } argon2; -       struct -       { - 	const char   *hash; -@@ -160,10 +161,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")) -@@ -459,6 +461,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.2 - diff --git a/config/grub/xhci/patches/0002-luks2/0007-Compile-with-Argon2id-support.patch b/config/grub/xhci/patches/0002-luks2/0007-Compile-with-Argon2id-support.patch deleted file mode 100644 index f2e26fd4..00000000 --- a/config/grub/xhci/patches/0002-luks2/0007-Compile-with-Argon2id-support.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0a21695c55f76f1c958bb633481d55b3168562f7 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 5/6] 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 1e9a13d3e..a167825c3 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 4a06789e5..e939dcc99 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -1238,7 +1238,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 bc818ea69..5b9eaa599 100644 ---- a/grub-core/disk/luks2.c -+++ b/grub-core/disk/luks2.c -@@ -27,6 +27,7 @@ - #include <grub/partition.h> - #include <grub/i18n.h> -  -+#include <argon2.h> - #include <base64.h> - #include <json.h> -  -@@ -462,8 +463,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.2 - diff --git a/config/grub/xhci/patches/0002-luks2/0008-Make-grub-install-work-with-Argon2.patch b/config/grub/xhci/patches/0002-luks2/0008-Make-grub-install-work-with-Argon2.patch deleted file mode 100644 index dc65b7a6..00000000 --- a/config/grub/xhci/patches/0002-luks2/0008-Make-grub-install-work-with-Argon2.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6c9a6625c0dc038d1bdbdc13665f40e269e86496 Mon Sep 17 00:00:00 2001 -From: Ax333l <main@axelen.xyz> -Date: Thu, 17 Aug 2023 00:00:00 +0000 -Subject: [PATCH 6/6] 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 1ad04db36..a8a3330b8 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.2 - diff --git a/config/grub/xhci/patches/0003-keyboardfix/0001-at_keyboard-coreboot-force-scancodes2-translate.patch b/config/grub/xhci/patches/0003-keyboardfix/0001-at_keyboard-coreboot-force-scancodes2-translate.patch deleted file mode 100644 index 21e8630b..00000000 --- a/config/grub/xhci/patches/0003-keyboardfix/0001-at_keyboard-coreboot-force-scancodes2-translate.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 96c0bbe5d406b616360a7fce7cee67d7692c0d6d Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Mon, 30 Oct 2023 22:19:21 +0000 -Subject: [PATCH 1/1] 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.2 - diff --git a/config/grub/xhci/patches/0003-keyboardfix/0002-keylayouts-don-t-print-Unknown-key-message.patch b/config/grub/xhci/patches/0003-keyboardfix/0002-keylayouts-don-t-print-Unknown-key-message.patch deleted file mode 100644 index fbef86a4..00000000 --- a/config/grub/xhci/patches/0003-keyboardfix/0002-keylayouts-don-t-print-Unknown-key-message.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0a6abeb40ac4284fbff6ef5958989d561b6290a7 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Tue, 31 Oct 2023 10:33:28 +0000 -Subject: [PATCH 1/1] 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.2 - diff --git a/config/grub/xhci/patches/0004-prefix/0001-don-t-print-missing-prefix-errors-on-the-screen.patch b/config/grub/xhci/patches/0004-prefix/0001-don-t-print-missing-prefix-errors-on-the-screen.patch deleted file mode 100644 index 25091d16..00000000 --- a/config/grub/xhci/patches/0004-prefix/0001-don-t-print-missing-prefix-errors-on-the-screen.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 9e7a651a0f15f2e9dec65a77765c3c4fd97b4165 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 5 Nov 2023 16:14:58 +0000 -Subject: [PATCH 1/1] 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 4011e2d15..af3bd00d0 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -758,7 +758,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.2 - diff --git a/config/grub/xhci/patches/0004-prefix/0002-don-t-print-error-if-module-not-found.patch b/config/grub/xhci/patches/0004-prefix/0002-don-t-print-error-if-module-not-found.patch deleted file mode 100644 index f4cf939e..00000000 --- a/config/grub/xhci/patches/0004-prefix/0002-don-t-print-error-if-module-not-found.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 6237c5762edccc1e1fa4746b1d4aa5e8d81e4883 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 5 Nov 2023 16:36:22 +0000 -Subject: [PATCH 1/1] 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 af3bd00d0..21d0cedb1 100644 ---- a/grub-core/kern/dl.c -+++ b/grub-core/kern/dl.c -@@ -486,7 +486,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.2 - diff --git a/config/grub/xhci/patches/0004-prefix/0003-don-t-print-empty-error-messages.patch b/config/grub/xhci/patches/0004-prefix/0003-don-t-print-empty-error-messages.patch deleted file mode 100644 index 25221c9c..00000000 --- a/config/grub/xhci/patches/0004-prefix/0003-don-t-print-empty-error-messages.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e5b7ec81421487e71bcaf8b6b5a27f3649a62753 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 5 Nov 2023 17:25:20 +0000 -Subject: [PATCH 1/1] 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0001-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch b/config/grub/xhci/patches/0005-xhci/0001-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch deleted file mode 100644 index f533269f..00000000 --- a/config/grub/xhci/patches/0005-xhci/0001-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch +++ /dev/null @@ -1,245 +0,0 @@ -From 90c9011f2e0350a97e3df44b0fc6dd022e04c276 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 1/8] 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0002-usb-Add-enum-for-xHCI.patch b/config/grub/xhci/patches/0005-xhci/0002-usb-Add-enum-for-xHCI.patch deleted file mode 100644 index d61da615..00000000 --- a/config/grub/xhci/patches/0005-xhci/0002-usb-Add-enum-for-xHCI.patch +++ /dev/null @@ -1,29 +0,0 @@ -From e111983ca5e2a52bfe2bdc5cd639b06bb2f7902d Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Sun, 15 Nov 2020 19:47:06 +0100 -Subject: [PATCH 2/8] 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0003-usbtrans-Set-default-maximum-packet-size.patch b/config/grub/xhci/patches/0005-xhci/0003-usbtrans-Set-default-maximum-packet-size.patch deleted file mode 100644 index 70e73ca2..00000000 --- a/config/grub/xhci/patches/0005-xhci/0003-usbtrans-Set-default-maximum-packet-size.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 3e25c83a1d1c6e149c7e9f0660ddadb2beca2476 Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Sun, 15 Nov 2020 19:48:03 +0100 -Subject: [PATCH 3/8] 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0004-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch b/config/grub/xhci/patches/0005-xhci/0004-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch deleted file mode 100644 index a090e0ea..00000000 --- a/config/grub/xhci/patches/0005-xhci/0004-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 89701aba00caa81bb566ab10da0c89264393be30 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 4/8] 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 9abebc6bd..953b851c0 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0005-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch b/config/grub/xhci/patches/0005-xhci/0005-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch deleted file mode 100644 index 7d69c3a6..00000000 --- a/config/grub/xhci/patches/0005-xhci/0005-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 5e5d74a4531770258e21dedd45c33f1a9d3afa6b Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Sun, 15 Nov 2020 19:54:40 +0100 -Subject: [PATCH 5/8] 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0006-grub-core-bus-usb-Add-xhci-support.patch b/config/grub/xhci/patches/0005-xhci/0006-grub-core-bus-usb-Add-xhci-support.patch deleted file mode 100644 index 11df42d8..00000000 --- a/config/grub/xhci/patches/0005-xhci/0006-grub-core-bus-usb-Add-xhci-support.patch +++ /dev/null @@ -1,2814 +0,0 @@ -From fe3a0bce527e059e9121eb5ad2c3cc099f07a4bf Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Sun, 15 Nov 2020 19:59:25 +0100 -Subject: [PATCH 6/8] 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 - -Tested on qemu using coreboot and grub as payload: - -qemu-system-x86_64 -M q35 -bios $firmware -device qemu-xhci,id=xhci -accel kvm -m 1024M \ -	-device usb-storage,drive=thumbdrive,bus=xhci.0,port=3 \ -	-drive if=none,format=raw,id=thumbdrive,file=ubuntu-20.04.1-desktop-amd64.iso \ -	-device usb-kbd,bus=xhci.0 - -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 fb6078a34..64c3806ab 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0007-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch b/config/grub/xhci/patches/0005-xhci/0007-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch deleted file mode 100644 index a37bbd6b..00000000 --- a/config/grub/xhci/patches/0005-xhci/0007-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 2a2c64f6ea62337c1263a70f6ca9a9bade66b78b Mon Sep 17 00:00:00 2001 -From: Patrick Rudolph <patrick.rudolph@9elements.com> -Date: Thu, 3 Dec 2020 13:44:55 +0100 -Subject: [PATCH 7/8] 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.2 - diff --git a/config/grub/xhci/patches/0005-xhci/0008-Fix-compilation-on-x86_64.patch b/config/grub/xhci/patches/0005-xhci/0008-Fix-compilation-on-x86_64.patch deleted file mode 100644 index af79c3d0..00000000 --- a/config/grub/xhci/patches/0005-xhci/0008-Fix-compilation-on-x86_64.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 871d768f8c5c960cb0d9761a9028b16882e1a7d3 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 8/8] 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 f4591ffb5..3495bb919 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) - { -@@ -664,7 +672,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; -@@ -697,9 +705,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); -     } - } -  -@@ -800,7 +808,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)) -     { -@@ -1907,7 +1915,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); -  -@@ -1974,7 +1982,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.2 - diff --git a/config/grub/xhci/patches/0006-nvme/0001-Add-native-NVMe-driver-based-on-SeaBIOS.patch b/config/grub/xhci/patches/0006-nvme/0001-Add-native-NVMe-driver-based-on-SeaBIOS.patch deleted file mode 100644 index b00611a0..00000000 --- a/config/grub/xhci/patches/0006-nvme/0001-Add-native-NVMe-driver-based-on-SeaBIOS.patch +++ /dev/null @@ -1,1074 +0,0 @@ -From ef9d61ae9ed490301adf9ee064a9fc1190069d81 Mon Sep 17 00:00:00 2001 -From: Mate Kukri <km@mkukri.xyz> -Date: Mon, 20 May 2024 11:43:35 +0100 -Subject: 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 ea782666d..0f893369a 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2602,3 +2602,9 @@ module = { -   efi = commands/bli.c; -   enable = efi; - }; -+ -+module = { -+  name = nvme; -+  common = disk/nvme.c; -+  enable = pci; -+}; -diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c -index 580c8d3b0..a2c766fbd 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.2 - | 
