diff options
Diffstat (limited to 'config/grub/patches')
14 files changed, 0 insertions, 4360 deletions
diff --git a/config/grub/patches/0001-borderfix/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch b/config/grub/patches/0001-borderfix/0001-mitigate-grub-s-missing-characters-for-borders-arrow.patch deleted file mode 100644 index 183f5a91..00000000 --- a/config/grub/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/patches/0001-borderfix/0002-say-the-name-libreboot-in-the-grub-menu.patch b/config/grub/patches/0001-borderfix/0002-say-the-name-libreboot-in-the-grub-menu.patch deleted file mode 100644 index 6ff97979..00000000 --- a/config/grub/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/patches/0002-luks2/0003-Add-CC0-license.patch b/config/grub/patches/0002-luks2/0003-Add-CC0-license.patch deleted file mode 100644 index dc9060c3..00000000 --- a/config/grub/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/patches/0002-luks2/0004-Define-GRUB_UINT32_MAX.patch b/config/grub/patches/0002-luks2/0004-Define-GRUB_UINT32_MAX.patch deleted file mode 100644 index be875e67..00000000 --- a/config/grub/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/patches/0002-luks2/0005-Add-Argon2-algorithm.patch b/config/grub/patches/0002-luks2/0005-Add-Argon2-algorithm.patch deleted file mode 100644 index 1c6b4f04..00000000 --- a/config/grub/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/patches/0002-luks2/0006-Error-on-missing-Argon2id-parameters.patch b/config/grub/patches/0002-luks2/0006-Error-on-missing-Argon2id-parameters.patch deleted file mode 100644 index 5d56bd61..00000000 --- a/config/grub/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/patches/0002-luks2/0007-Compile-with-Argon2id-support.patch b/config/grub/patches/0002-luks2/0007-Compile-with-Argon2id-support.patch deleted file mode 100644 index f2e26fd4..00000000 --- a/config/grub/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/patches/0002-luks2/0008-Make-grub-install-work-with-Argon2.patch b/config/grub/patches/0002-luks2/0008-Make-grub-install-work-with-Argon2.patch deleted file mode 100644 index dc65b7a6..00000000 --- a/config/grub/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/patches/0003-keyboardfix/0001-at_keyboard-coreboot-force-scancodes2-translate.patch b/config/grub/patches/0003-keyboardfix/0001-at_keyboard-coreboot-force-scancodes2-translate.patch deleted file mode 100644 index 21e8630b..00000000 --- a/config/grub/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/patches/0003-keyboardfix/0002-keylayouts-don-t-print-Unknown-key-message.patch b/config/grub/patches/0003-keyboardfix/0002-keylayouts-don-t-print-Unknown-key-message.patch deleted file mode 100644 index fbef86a4..00000000 --- a/config/grub/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/patches/0004-prefix/0001-don-t-print-missing-prefix-errors-on-the-screen.patch b/config/grub/patches/0004-prefix/0001-don-t-print-missing-prefix-errors-on-the-screen.patch deleted file mode 100644 index 25091d16..00000000 --- a/config/grub/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/patches/0004-prefix/0002-don-t-print-error-if-module-not-found.patch b/config/grub/patches/0004-prefix/0002-don-t-print-error-if-module-not-found.patch deleted file mode 100644 index f4cf939e..00000000 --- a/config/grub/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/patches/0004-prefix/0003-don-t-print-empty-error-messages.patch b/config/grub/patches/0004-prefix/0003-don-t-print-empty-error-messages.patch deleted file mode 100644 index 25221c9c..00000000 --- a/config/grub/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/patches/0006-nvme/0001-Add-native-NVMe-driver-based-on-SeaBIOS.patch b/config/grub/patches/0006-nvme/0001-Add-native-NVMe-driver-based-on-SeaBIOS.patch deleted file mode 100644 index 4345ebae..00000000 --- a/config/grub/patches/0006-nvme/0001-Add-native-NVMe-driver-based-on-SeaBIOS.patch +++ /dev/null @@ -1,1074 +0,0 @@ -From 708c0092d44aec6409e0ecc1925cdbb3b76c6dfd Mon Sep 17 00:00:00 2001 -From: Mate Kukri <km@mkukri.xyz> -Date: Mon, 20 May 2024 11:43:35 +0100 -Subject: [PATCH 1/1] 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 43635d5ff..2c86dbbf6 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 nvme 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 560c66447..d3bf9f1c5 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2607,3 +2607,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 6806bff9c..fd68a513e 100644 ---- a/grub-core/commands/nativedisk.c -+++ b/grub-core/commands/nativedisk.c -@@ -78,6 +78,7 @@ get_uuid (const char *name, char **uuid, int getnative) - case GRUB_DISK_DEVICE_ATA_ID: - case GRUB_DISK_DEVICE_SCSI_ID: - case GRUB_DISK_DEVICE_XEN: -+ case GRUB_DISK_DEVICE_NVME_ID: - if (getnative) - break; - /* FALLTHROUGH */ -diff --git a/grub-core/disk/nvme-int.h b/grub-core/disk/nvme-int.h -new file mode 100644 -index 000000000..1295b58aa ---- /dev/null -+++ b/grub-core/disk/nvme-int.h -@@ -0,0 +1,208 @@ -+// NVMe datastructures and constants -+// -+// Copyright 2017 Amazon.com, Inc. or its affiliates. -+// -+// This file may be distributed under the terms of the GNU LGPLv3 license. -+ -+#ifndef __NVME_INT_H -+#define __NVME_INT_H -+ -+#include <grub/types.h> -+ -+/* Data structures */ -+ -+/* The register file of a NVMe host controller. This struct follows the naming -+ scheme in the NVMe specification. */ -+struct nvme_reg { -+ grub_uint64_t cap; /* controller capabilities */ -+ grub_uint32_t vs; /* version */ -+ grub_uint32_t intms; /* interrupt mask set */ -+ grub_uint32_t intmc; /* interrupt mask clear */ -+ grub_uint32_t cc; /* controller configuration */ -+ grub_uint32_t _res0; -+ grub_uint32_t csts; /* controller status */ -+ grub_uint32_t _res1; -+ grub_uint32_t aqa; /* admin queue attributes */ -+ grub_uint64_t asq; /* admin submission queue base address */ -+ grub_uint64_t acq; /* admin completion queue base address */ -+}; -+ -+/* Submission queue entry */ -+struct nvme_sqe { -+ union { -+ grub_uint32_t dword[16]; -+ struct { -+ grub_uint32_t cdw0; /* Command DWORD 0 */ -+ grub_uint32_t nsid; /* Namespace ID */ -+ grub_uint64_t _res0; -+ grub_uint64_t mptr; /* metadata ptr */ -+ -+ grub_uint64_t dptr_prp1; -+ grub_uint64_t dptr_prp2; -+ }; -+ }; -+}; -+ -+/* Completion queue entry */ -+struct nvme_cqe { -+ union { -+ grub_uint32_t dword[4]; -+ struct { -+ grub_uint32_t cdw0; -+ grub_uint32_t _res0; -+ grub_uint16_t sq_head; -+ grub_uint16_t sq_id; -+ grub_uint16_t cid; -+ grub_uint16_t status; -+ }; -+ }; -+}; -+ -+/* The common part of every submission or completion queue. */ -+struct nvme_queue { -+ grub_uint32_t *dbl; /* doorbell */ -+ grub_uint16_t mask; /* length - 1 */ -+}; -+ -+struct nvme_cq { -+ struct nvme_queue common; -+ struct nvme_cqe *cqe; -+ -+ /* We have read upto (but not including) this entry in the queue. */ -+ grub_uint16_t head; -+ -+ /* The current phase bit the controller uses to indicate that it has written -+ a new entry. This is inverted after each wrap. */ -+ unsigned phase : 1; -+}; -+ -+struct nvme_sq { -+ struct nvme_queue common; -+ struct nvme_sqe *sqe; -+ -+ /* Corresponding completion queue. We only support a single SQ per CQ. */ -+ struct nvme_cq *cq; -+ -+ /* The last entry the controller has fetched. */ -+ grub_uint16_t head; -+ -+ /* The last value we have written to the tail doorbell. */ -+ grub_uint16_t tail; -+}; -+ -+struct nvme_ctrl { -+ grub_pci_device_t pci; -+ struct nvme_reg volatile *reg; -+ -+ grub_uint32_t ctrlnum; -+ -+ grub_uint32_t doorbell_stride; /* in bytes */ -+ -+ struct nvme_sq admin_sq; -+ struct nvme_cq admin_cq; -+ -+ grub_uint32_t ns_count; -+ -+ struct nvme_sq io_sq; -+ struct nvme_cq io_cq; -+}; -+ -+struct nvme_namespace { -+ struct nvme_namespace *next; -+ struct nvme_namespace **prev; -+ -+ char *devname; -+ -+ grub_uint32_t nsnum; -+ -+ struct nvme_ctrl *ctrl; -+ -+ grub_uint32_t ns_id; -+ -+ grub_uint64_t lba_count; /* The total amount of sectors. */ -+ -+ grub_uint32_t block_size; -+ grub_uint32_t metadata_size; -+ grub_uint32_t max_req_size; -+}; -+ -+/* Data structures for NVMe admin identify commands */ -+ -+struct nvme_identify_ctrl { -+ grub_uint16_t vid; -+ grub_uint16_t ssvid; -+ char sn[20]; -+ char mn[40]; -+ char fr[8]; -+ -+ grub_uint8_t rab; -+ grub_uint8_t ieee[3]; -+ grub_uint8_t cmic; -+ grub_uint8_t mdts; -+ -+ char _boring[516 - 78]; -+ -+ grub_uint32_t nn; /* number of namespaces */ -+}; -+ -+struct nvme_identify_ns_list { -+ grub_uint32_t ns_id[1024]; -+}; -+ -+struct nvme_lba_format { -+ grub_uint16_t ms; -+ grub_uint8_t lbads; -+ grub_uint8_t rp; -+}; -+ -+struct nvme_identify_ns { -+ grub_uint64_t nsze; -+ grub_uint64_t ncap; -+ grub_uint64_t nuse; -+ grub_uint8_t nsfeat; -+ grub_uint8_t nlbaf; -+ grub_uint8_t flbas; -+ -+ char _boring[128 - 27]; -+ -+ struct nvme_lba_format lbaf[16]; -+}; -+ -+union nvme_identify { -+ struct nvme_identify_ns ns; -+ struct nvme_identify_ctrl ctrl; -+ struct nvme_identify_ns_list ns_list; -+}; -+ -+/* NVMe constants */ -+ -+#define NVME_CAP_CSS_NVME (1ULL << 37) -+ -+#define NVME_CSTS_FATAL (1U << 1) -+#define NVME_CSTS_RDY (1U << 0) -+ -+#define NVME_CC_EN (1U << 0) -+ -+#define NVME_SQE_OPC_ADMIN_CREATE_IO_SQ 1U -+#define NVME_SQE_OPC_ADMIN_CREATE_IO_CQ 5U -+#define NVME_SQE_OPC_ADMIN_IDENTIFY 6U -+ -+#define NVME_SQE_OPC_IO_WRITE 1U -+#define NVME_SQE_OPC_IO_READ 2U -+ -+#define NVME_ADMIN_IDENTIFY_CNS_ID_NS 0U -+#define NVME_ADMIN_IDENTIFY_CNS_ID_CTRL 1U -+#define NVME_ADMIN_IDENTIFY_CNS_GET_NS_LIST 2U -+ -+#define NVME_CQE_DW3_P (1U << 16) -+ -+#define NVME_PAGE_SIZE 4096 -+#define NVME_PAGE_MASK ~(NVME_PAGE_SIZE - 1) -+ -+/* Length for the queue entries. */ -+#define NVME_SQE_SIZE_LOG 6 -+#define NVME_CQE_SIZE_LOG 4 -+ -+#endif -+ -+/* EOF */ -diff --git a/grub-core/disk/nvme.c b/grub-core/disk/nvme.c -new file mode 100644 -index 000000000..093237c70 ---- /dev/null -+++ b/grub-core/disk/nvme.c -@@ -0,0 +1,781 @@ -+// Low level NVMe disk access -+// -+// Based on SeaBIOS NVMe driver - Copyright 2017 Amazon.com, Inc. or its affiliates. -+// Port to GRUB2 done by Mate Kukri -+// -+// This file may be distributed under the terms of the GNU LGPLv3 license. -+ -+#include <grub/disk.h> -+#include <grub/dl.h> -+#include <grub/pci.h> -+#include "nvme-int.h" -+ -+GRUB_MOD_LICENSE ("GPLv3"); /* LGPLv3 in reality but it is GPLv3 compatible */ -+ -+static grub_uint32_t grub_nvme_ctrlcnt; -+static grub_uint32_t grub_nvme_nscnt; -+ -+static struct nvme_namespace *grub_nvme_namespaces; -+ -+// Page aligned "dma bounce buffer" of size NVME_PAGE_SIZE -+static void *nvme_dma_buffer; -+ -+static void * -+zalloc_page_aligned(grub_uint32_t size) -+{ -+ void *res = grub_memalign(NVME_PAGE_SIZE, size); -+ if (res) grub_memset(res, 0, size); -+ return res; -+} -+ -+static void -+nvme_init_queue_common(struct nvme_ctrl *ctrl, struct nvme_queue *q, grub_uint16_t q_idx, -+ grub_uint16_t length) -+{ -+ grub_memset(q, 0, sizeof(*q)); -+ q->dbl = (grub_uint32_t *)((char *)ctrl->reg + 0x1000 + q_idx * ctrl->doorbell_stride); -+ grub_dprintf("nvme", " q %p q_idx %u dbl %p\n", q, q_idx, q->dbl); -+ q->mask = length - 1; -+} -+ -+static int -+nvme_init_sq(struct nvme_ctrl *ctrl, struct nvme_sq *sq, grub_uint16_t q_idx, grub_uint16_t length, -+ struct nvme_cq *cq) -+{ -+ nvme_init_queue_common(ctrl, &sq->common, q_idx, length); -+ sq->sqe = zalloc_page_aligned(sizeof(*sq->sqe) * length); -+ -+ if (!sq->sqe) { -+ return -1; -+ } -+ -+ grub_dprintf("nvme", "sq %p q_idx %u sqe %p\n", sq, q_idx, sq->sqe); -+ sq->cq = cq; -+ sq->head = 0; -+ sq->tail = 0; -+ -+ return 0; -+} -+ -+static int -+nvme_init_cq(struct nvme_ctrl *ctrl, struct nvme_cq *cq, grub_uint16_t q_idx, grub_uint16_t length) -+{ -+ nvme_init_queue_common(ctrl, &cq->common, q_idx, length); -+ cq->cqe = zalloc_page_aligned(sizeof(*cq->cqe) * length); -+ if (!cq->cqe) { -+ return -1; -+ } -+ -+ cq->head = 0; -+ -+ /* All CQE phase bits are initialized to zero. This means initially we wait -+ for the host controller to set these to 1. */ -+ cq->phase = 1; -+ -+ return 0; -+} -+ -+static int -+nvme_poll_cq(struct nvme_cq *cq) -+{ -+ grub_uint32_t dw3 = *(volatile grub_uint32_t *) &cq->cqe[cq->head].dword[3]; -+ return (!!(dw3 & NVME_CQE_DW3_P) == cq->phase); -+} -+ -+static int -+nvme_is_cqe_success(struct nvme_cqe const *cqe) -+{ -+ return ((cqe->status >> 1) & 0xFF) == 0; -+} -+ -+static struct nvme_cqe -+nvme_error_cqe(void) -+{ -+ struct nvme_cqe r; -+ -+ /* 0xFF is a vendor specific status code != success. Should be okay for -+ indicating failure. */ -+ grub_memset(&r, 0xFF, sizeof(r)); -+ return r; -+} -+ -+static struct nvme_cqe -+nvme_consume_cqe(struct nvme_sq *sq) -+{ -+ struct nvme_cq *cq = sq->cq; -+ -+ if (!nvme_poll_cq(cq)) { -+ /* Cannot consume a completion queue entry, if there is none ready. */ -+ return nvme_error_cqe(); -+ } -+ -+ struct nvme_cqe *cqe = &cq->cqe[cq->head]; -+ grub_uint16_t cq_next_head = (cq->head + 1) & cq->common.mask; -+ grub_dprintf("nvme", "cq %p head %u -> %u\n", cq, cq->head, cq_next_head); -+ if (cq_next_head < cq->head) { -+ grub_dprintf("nvme", "cq %p wrap\n", cq); -+ cq->phase = ~cq->phase; -+ } -+ cq->head = cq_next_head; -+ -+ /* Update the submission queue head. */ -+ if (cqe->sq_head != sq->head) { -+ sq->head = cqe->sq_head; -+ grub_dprintf("nvme", "sq %p advanced to %u\n", sq, cqe->sq_head); -+ } -+ -+ /* Tell the controller that we consumed the completion. */ -+ *(volatile grub_uint32_t *) cq->common.dbl = cq->head; -+ -+ return *cqe; -+} -+ -+static struct nvme_cqe -+nvme_wait(struct nvme_sq *sq) -+{ -+ // static const unsigned nvme_timeout = 5000 /* ms */; -+ // grub_uint32_t to = timer_calc(nvme_timeout); -+ while (!nvme_poll_cq(sq->cq)) { -+ /* FIXME -+ yield(); -+ -+ if (timer_check(to)) { -+ warn_timeout(); -+ return nvme_error_cqe(); -+ }*/ -+ } -+ -+ return nvme_consume_cqe(sq); -+} -+ -+/* Returns the next submission queue entry (or NULL if the queue is full). It -+ also fills out Command Dword 0 and clears the rest. */ -+static struct nvme_sqe * -+nvme_get_next_sqe(struct nvme_sq *sq, grub_uint8_t opc, void *metadata, void *data, void *data2) -+{ -+ if (((sq->head + 1) & sq->common.mask) == sq->tail) { -+ grub_dprintf("nvme", "submission queue is full\n"); -+ return NULL; -+ } -+ -+ struct nvme_sqe *sqe = &sq->sqe[sq->tail]; -+ grub_dprintf("nvme", "sq %p next_sqe %u\n", sq, sq->tail); -+ -+ grub_memset(sqe, 0, sizeof(*sqe)); -+ sqe->cdw0 = opc | (sq->tail << 16 /* CID */); -+ sqe->mptr = (grub_uint32_t)metadata; -+ sqe->dptr_prp1 = (grub_uint32_t)data; -+ sqe->dptr_prp2 = (grub_uint32_t)data2; -+ -+ return sqe; -+} -+ -+/* Call this after you've filled out an sqe that you've got from nvme_get_next_sqe. */ -+static void -+nvme_commit_sqe(struct nvme_sq *sq) -+{ -+ grub_dprintf("nvme", "sq %p commit_sqe %u\n", sq, sq->tail); -+ sq->tail = (sq->tail + 1) & sq->common.mask; -+ *(volatile grub_uint32_t *) sq->common.dbl = sq->tail; -+} -+ -+/* Perform an identify command on the admin queue and return the resulting -+ buffer. This may be a NULL pointer, if something failed. This function -+ cannot be used after initialization, because it uses buffers in tmp zone. */ -+static union nvme_identify * -+nvme_admin_identify(struct nvme_ctrl *ctrl, grub_uint8_t cns, grub_uint32_t nsid) -+{ -+ union nvme_identify *identify_buf = zalloc_page_aligned(4096); -+ if (!identify_buf) -+ return NULL; -+ -+ struct nvme_sqe *cmd_identify; -+ cmd_identify = nvme_get_next_sqe(&ctrl->admin_sq, -+ NVME_SQE_OPC_ADMIN_IDENTIFY, NULL, -+ identify_buf, NULL); -+ if (!cmd_identify) -+ goto error; -+ -+ cmd_identify->nsid = nsid; -+ cmd_identify->dword[10] = cns; -+ -+ nvme_commit_sqe(&ctrl->admin_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ctrl->admin_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ goto error; -+ } -+ -+ return identify_buf; -+ error: -+ grub_free(identify_buf); -+ return NULL; -+} -+ -+static struct nvme_identify_ctrl * -+nvme_admin_identify_ctrl(struct nvme_ctrl *ctrl) -+{ -+ return &nvme_admin_identify(ctrl, NVME_ADMIN_IDENTIFY_CNS_ID_CTRL, 0)->ctrl; -+} -+ -+static struct nvme_identify_ns * -+nvme_admin_identify_ns(struct nvme_ctrl *ctrl, grub_uint32_t ns_id) -+{ -+ return &nvme_admin_identify(ctrl, NVME_ADMIN_IDENTIFY_CNS_ID_NS, -+ ns_id)->ns; -+} -+ -+static void -+nvme_probe_ns(struct nvme_ctrl *ctrl, grub_uint32_t ns_idx, grub_uint8_t mdts) -+{ -+ grub_uint32_t ns_id = ns_idx + 1; -+ -+ struct nvme_identify_ns *id = nvme_admin_identify_ns(ctrl, ns_id); -+ if (!id) { -+ grub_dprintf("nvme", "NVMe couldn't identify namespace %u.\n", ns_id); -+ goto free_buffer; -+ } -+ -+ grub_uint8_t current_lba_format = id->flbas & 0xF; -+ if (current_lba_format > id->nlbaf) { -+ grub_dprintf("nvme", "NVMe NS %u: current LBA format %u is beyond what the " -+ " namespace supports (%u)?\n", -+ ns_id, current_lba_format, id->nlbaf + 1); -+ goto free_buffer; -+ } -+ -+ if (!id->nsze) { -+ grub_dprintf("nvme", "NVMe NS %u is inactive.\n", ns_id); -+ goto free_buffer; -+ } -+ -+ if (!nvme_dma_buffer) { -+ nvme_dma_buffer = zalloc_page_aligned(NVME_PAGE_SIZE); -+ if (!nvme_dma_buffer) { -+ goto free_buffer; -+ } -+ } -+ -+ struct nvme_namespace *ns = grub_malloc(sizeof(*ns)); -+ if (!ns) { -+ goto free_buffer; -+ } -+ grub_memset(ns, 0, sizeof(*ns)); -+ ns->ctrl = ctrl; -+ ns->ns_id = ns_id; -+ ns->lba_count = id->nsze; -+ -+ struct nvme_lba_format *fmt = &id->lbaf[current_lba_format]; -+ -+ ns->block_size = 1U << fmt->lbads; -+ ns->metadata_size = fmt->ms; -+ -+ if (ns->block_size > NVME_PAGE_SIZE) { -+ /* If we see devices that trigger this path, we need to increase our -+ buffer size. */ -+ grub_free(ns); -+ goto free_buffer; -+ } -+ -+ if (mdts) { -+ ns->max_req_size = ((1U << mdts) * NVME_PAGE_SIZE) / ns->block_size; -+ grub_dprintf("nvme", "NVME NS %u max request size: %d sectors\n", -+ ns_id, ns->max_req_size); -+ } else { -+ ns->max_req_size = -1U; -+ } -+ -+ ns->devname = grub_xasprintf("nvme%un%u", ctrl->ctrlnum, ns_id); -+ ns->nsnum = grub_nvme_nscnt++; -+ -+ grub_list_push (GRUB_AS_LIST_P (&grub_nvme_namespaces), GRUB_AS_LIST (ns)); -+ -+free_buffer: -+ grub_free(id); -+} -+ -+ -+/* Release memory allocated for a completion queue */ -+static void -+nvme_destroy_cq(struct nvme_cq *cq) -+{ -+ grub_free(cq->cqe); -+ cq->cqe = NULL; -+} -+ -+/* Release memory allocated for a submission queue */ -+static void -+nvme_destroy_sq(struct nvme_sq *sq) -+{ -+ grub_free(sq->sqe); -+ sq->sqe = NULL; -+} -+ -+/* Returns 0 on success. */ -+static int -+nvme_create_io_cq(struct nvme_ctrl *ctrl, struct nvme_cq *cq, grub_uint16_t q_idx) -+{ -+ int rc; -+ struct nvme_sqe *cmd_create_cq; -+ grub_uint32_t length = 1 + (ctrl->reg->cap & 0xffff); -+ if (length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe)) -+ length = NVME_PAGE_SIZE / sizeof(struct nvme_cqe); -+ -+ rc = nvme_init_cq(ctrl, cq, q_idx, length); -+ if (rc) { -+ goto err; -+ } -+ -+ cmd_create_cq = nvme_get_next_sqe(&ctrl->admin_sq, -+ NVME_SQE_OPC_ADMIN_CREATE_IO_CQ, NULL, -+ cq->cqe, NULL); -+ if (!cmd_create_cq) { -+ goto err_destroy_cq; -+ } -+ -+ cmd_create_cq->dword[10] = (cq->common.mask << 16) | (q_idx >> 1); -+ cmd_create_cq->dword[11] = 1 /* physically contiguous */; -+ -+ nvme_commit_sqe(&ctrl->admin_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ctrl->admin_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ grub_dprintf("nvme", "create io cq failed: %08x %08x %08x %08x\n", -+ cqe.dword[0], cqe.dword[1], cqe.dword[2], cqe.dword[3]); -+ -+ goto err_destroy_cq; -+ } -+ -+ return 0; -+ -+err_destroy_cq: -+ nvme_destroy_cq(cq); -+err: -+ return -1; -+} -+ -+/* Returns 0 on success. */ -+static int -+nvme_create_io_sq(struct nvme_ctrl *ctrl, struct nvme_sq *sq, grub_uint16_t q_idx, struct nvme_cq *cq) -+{ -+ int rc; -+ struct nvme_sqe *cmd_create_sq; -+ grub_uint32_t length = 1 + (ctrl->reg->cap & 0xffff); -+ if (length > NVME_PAGE_SIZE / sizeof(struct nvme_cqe)) -+ length = NVME_PAGE_SIZE / sizeof(struct nvme_cqe); -+ -+ rc = nvme_init_sq(ctrl, sq, q_idx, length, cq); -+ if (rc) { -+ goto err; -+ } -+ -+ cmd_create_sq = nvme_get_next_sqe(&ctrl->admin_sq, -+ NVME_SQE_OPC_ADMIN_CREATE_IO_SQ, NULL, -+ sq->sqe, NULL); -+ if (!cmd_create_sq) { -+ goto err_destroy_sq; -+ } -+ -+ cmd_create_sq->dword[10] = (sq->common.mask << 16) | (q_idx >> 1); -+ cmd_create_sq->dword[11] = (q_idx >> 1) << 16 | 1 /* contiguous */; -+ grub_dprintf("nvme", "sq %p create dword10 %08x dword11 %08x\n", sq, -+ cmd_create_sq->dword[10], cmd_create_sq->dword[11]); -+ -+ nvme_commit_sqe(&ctrl->admin_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ctrl->admin_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ grub_dprintf("nvme", "create io sq failed: %08x %08x %08x %08x\n", -+ cqe.dword[0], cqe.dword[1], cqe.dword[2], cqe.dword[3]); -+ goto err_destroy_sq; -+ } -+ -+ return 0; -+ -+err_destroy_sq: -+ nvme_destroy_sq(sq); -+err: -+ return -1; -+} -+ -+/* Reads count sectors into buf. The buffer cannot cross page boundaries. */ -+static int -+nvme_io_xfer(struct nvme_namespace *ns, grub_uint64_t lba, void *prp1, void *prp2, -+ grub_uint16_t count, int write) -+{ -+ if (((grub_uint32_t)prp1 & 0x3) || ((grub_uint32_t)prp2 & 0x3)) { -+ /* Buffer is misaligned */ -+ return -1; -+ } -+ -+ struct nvme_sqe *io_read = nvme_get_next_sqe(&ns->ctrl->io_sq, -+ write ? NVME_SQE_OPC_IO_WRITE -+ : NVME_SQE_OPC_IO_READ, -+ NULL, prp1, prp2); -+ io_read->nsid = ns->ns_id; -+ io_read->dword[10] = (grub_uint32_t)lba; -+ io_read->dword[11] = (grub_uint32_t)(lba >> 32); -+ io_read->dword[12] = (1U << 31 /* limited retry */) | (count - 1); -+ -+ nvme_commit_sqe(&ns->ctrl->io_sq); -+ -+ struct nvme_cqe cqe = nvme_wait(&ns->ctrl->io_sq); -+ -+ if (!nvme_is_cqe_success(&cqe)) { -+ grub_dprintf("nvme", "read io: %08x %08x %08x %08x\n", -+ cqe.dword[0], cqe.dword[1], cqe.dword[2], cqe.dword[3]); -+ -+ return -1; -+ } -+ -+ grub_dprintf("nvme", "ns %u %s lba %llu+%u\n", ns->ns_id, write ? "write" : "read", -+ lba, count); -+ return count; -+} -+ -+// Transfer up to one page of data using the internal dma bounce buffer -+static int -+nvme_bounce_xfer(struct nvme_namespace *ns, grub_uint64_t lba, void *buf, grub_uint16_t count, -+ int write) -+{ -+ grub_uint16_t const max_blocks = NVME_PAGE_SIZE / ns->block_size; -+ grub_uint16_t blocks = count < max_blocks ? count : max_blocks; -+ -+ if (write) -+ grub_memcpy(nvme_dma_buffer, buf, blocks * ns->block_size); -+ -+ int res = nvme_io_xfer(ns, lba, nvme_dma_buffer, NULL, blocks, write); -+ -+ if (!write && res >= 0) -+ grub_memcpy(buf, nvme_dma_buffer, res * ns->block_size); -+ -+ return res; -+} -+ -+#define NVME_MAX_PRPL_ENTRIES 15 /* Allows requests up to 64kb */ -+ -+// Transfer data using page list (if applicable) -+static int -+nvme_prpl_xfer(struct nvme_namespace *ns, grub_uint64_t lba, void *buf, grub_uint16_t count, -+ int write) -+{ -+ grub_uint32_t base = (long)buf; -+ grub_int32_t size; -+ -+ if (count > ns->max_req_size) -+ count = ns->max_req_size; -+ -+ size = count * ns->block_size; -+ /* Special case for transfers that fit into PRP1, but are unaligned */ -+ if (((size + (base & ~NVME_PAGE_MASK)) <= NVME_PAGE_SIZE)) -+ goto single; -+ -+ /* Every request has to be page aligned */ -+ if (base & ~NVME_PAGE_MASK) -+ goto bounce; -+ -+ /* Make sure a full block fits into the last chunk */ -+ if (size & (ns->block_size - 1ULL)) -+ goto bounce; -+ -+ /* Build PRP list if we need to describe more than 2 pages */ -+ if ((ns->block_size * count) > (NVME_PAGE_SIZE * 2)) { -+ grub_uint32_t prpl_len = 0; -+ grub_uint64_t *prpl = nvme_dma_buffer; -+ int first_page = 1; -+ for (; size > 0; base += NVME_PAGE_SIZE, size -= NVME_PAGE_SIZE) { -+ if (first_page) { -+ /* First page is special */ -+ first_page = 0; -+ continue; -+ } -+ if (prpl_len >= NVME_MAX_PRPL_ENTRIES) -+ goto bounce; -+ prpl[prpl_len++] = base; -+ } -+ return nvme_io_xfer(ns, lba, buf, prpl, count, write); -+ } -+ -+ /* Directly embed the 2nd page if we only need 2 pages */ -+ if ((ns->block_size * count) > NVME_PAGE_SIZE) -+ return nvme_io_xfer(ns, lba, buf, (char *) buf + NVME_PAGE_SIZE, count, write); -+ -+single: -+ /* One page is enough, don't expose anything else */ -+ return nvme_io_xfer(ns, lba, buf, NULL, count, write); -+ -+bounce: -+ /* Use bounce buffer to make transfer */ -+ return nvme_bounce_xfer(ns, lba, buf, count, write); -+} -+ -+static int -+nvme_create_io_queues(struct nvme_ctrl *ctrl) -+{ -+ if (nvme_create_io_cq(ctrl, &ctrl->io_cq, 3)) -+ goto err; -+ -+ if (nvme_create_io_sq(ctrl, &ctrl->io_sq, 2, &ctrl->io_cq)) -+ goto err_free_cq; -+ -+ return 0; -+ -+ err_free_cq: -+ nvme_destroy_cq(&ctrl->io_cq); -+ err: -+ return -1; -+} -+ -+/* Waits for CSTS.RDY to match rdy. Returns 0 on success. */ -+static int -+nvme_wait_csts_rdy(struct nvme_ctrl *ctrl, unsigned rdy) -+{ -+ // grub_uint32_t const max_to = 500 /* ms */ * ((ctrl->reg->cap >> 24) & 0xFFU); -+ // grub_uint32_t to = timer_calc(max_to); -+ grub_uint32_t csts; -+ -+ while (rdy != ((csts = ctrl->reg->csts) & NVME_CSTS_RDY)) { -+ // FIXME -+ //yield(); -+ -+ if (csts & NVME_CSTS_FATAL) { -+ grub_dprintf("nvme", "NVMe fatal error during controller shutdown\n"); -+ return -1; -+ } -+ -+ /* -+ if (timer_check(to)) { -+ warn_timeout(); -+ return -1; -+ }*/ -+ } -+ -+ return 0; -+} -+ -+/* Returns 0 on success. */ -+static int grub_nvme_controller_enable(struct nvme_ctrl *ctrl) -+{ -+ grub_pci_address_t addr; -+ int rc; -+ -+ addr = grub_pci_make_address (ctrl->pci, GRUB_PCI_REG_COMMAND); -+ grub_pci_write_word (addr, grub_pci_read_word (addr) | GRUB_PCI_COMMAND_BUS_MASTER); -+ -+ /* Turn the controller off. */ -+ ctrl->reg->cc = 0; -+ if (nvme_wait_csts_rdy(ctrl, 0)) { -+ grub_dprintf("nvme", "NVMe fatal error during controller shutdown\n"); -+ return -1; -+ } -+ -+ ctrl->doorbell_stride = 4U << ((ctrl->reg->cap >> 32) & 0xF); -+ -+ rc = nvme_init_cq(ctrl, &ctrl->admin_cq, 1, -+ NVME_PAGE_SIZE / sizeof(struct nvme_cqe)); -+ if (rc) { -+ return -1; -+ } -+ -+ rc = nvme_init_sq(ctrl, &ctrl->admin_sq, 0, -+ NVME_PAGE_SIZE / sizeof(struct nvme_sqe), &ctrl->admin_cq); -+ if (rc) { -+ goto err_destroy_admin_cq; -+ } -+ -+ ctrl->reg->aqa = ctrl->admin_cq.common.mask << 16 -+ | ctrl->admin_sq.common.mask; -+ -+ ctrl->reg->asq = (grub_uint32_t)ctrl->admin_sq.sqe; -+ ctrl->reg->acq = (grub_uint32_t)ctrl->admin_cq.cqe; -+ -+ grub_dprintf("nvme", " admin submission queue: %p\n", ctrl->admin_sq.sqe); -+ grub_dprintf("nvme", " admin completion queue: %p\n", ctrl->admin_cq.cqe); -+ -+ ctrl->reg->cc = NVME_CC_EN | (NVME_CQE_SIZE_LOG << 20) -+ | (NVME_SQE_SIZE_LOG << 16 /* IOSQES */); -+ -+ if (nvme_wait_csts_rdy(ctrl, 1)) { -+ grub_dprintf("nvme", "NVMe fatal error while enabling controller\n"); -+ goto err_destroy_admin_sq; -+ } -+ -+ /* The admin queue is set up and the controller is ready. Let's figure out -+ what namespaces we have. */ -+ -+ struct nvme_identify_ctrl *identify = nvme_admin_identify_ctrl(ctrl); -+ -+ if (!identify) { -+ grub_dprintf("nvme", "NVMe couldn't identify controller.\n"); -+ goto err_destroy_admin_sq; -+ } -+ -+ grub_dprintf("nvme", "NVMe has %u namespace%s.\n", -+ identify->nn, (identify->nn == 1) ? "" : "s"); -+ -+ ctrl->ns_count = identify->nn; -+ grub_uint8_t mdts = identify->mdts; -+ grub_free(identify); -+ -+ if ((ctrl->ns_count == 0) || nvme_create_io_queues(ctrl)) { -+ /* No point to continue, if the controller says it doesn't have -+ namespaces or we couldn't create I/O queues. */ -+ goto err_destroy_admin_sq; -+ } -+ -+ /* Give the controller a global number */ -+ ctrl->ctrlnum = grub_nvme_ctrlcnt++; -+ -+ /* Populate namespace IDs */ -+ for (grub_uint32_t ns_idx = 0; ns_idx < ctrl->ns_count; ns_idx++) { -+ nvme_probe_ns(ctrl, ns_idx, mdts); -+ } -+ -+ grub_dprintf("nvme", "NVMe initialization complete!\n"); -+ return 0; -+ -+ err_destroy_admin_sq: -+ nvme_destroy_sq(&ctrl->admin_sq); -+ err_destroy_admin_cq: -+ nvme_destroy_cq(&ctrl->admin_cq); -+ return -1; -+} -+ -+static int grub_nvme_pci_probe(grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)), void *data __attribute__ ((unused))) -+{ -+ grub_pci_address_t addr; -+ grub_uint32_t class, bar, version; -+ struct nvme_reg volatile *reg; -+ -+ class = grub_pci_read (grub_pci_make_address (dev, GRUB_PCI_REG_CLASS)); -+ if (class >> 16 != 0x0108) -+ return 0; -+ if ((class >> 8 & 0xff) != 2) { /* as of NVM 1.0e */ -+ grub_dprintf("nvme", "Found incompatble NVMe: prog-if=%02x\n", class >> 8 & 0xff); -+ return 0; -+ } -+ -+ bar = grub_pci_read (grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0)); -+ reg = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, sizeof (*reg)); -+ -+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); -+ grub_pci_write_word (addr, grub_pci_read_word (addr) | GRUB_PCI_COMMAND_MEM_ENABLED); -+ -+ version = reg->vs; -+ grub_dprintf("nvme", "Found NVMe controller with version %u.%u.%u.\n", version >> 16, (version >> 8) & 0xFF, version & 0xFF); -+ grub_dprintf("nvme", " Capabilities %016llx\n", reg->cap); -+ -+ if (~reg->cap & NVME_CAP_CSS_NVME) { -+ grub_dprintf("nvme", "Controller doesn't speak NVMe command set. Skipping.\n"); -+ goto err; -+ } -+ -+ struct nvme_ctrl *ctrl = grub_malloc(sizeof(*ctrl)); -+ if (!ctrl) -+ goto err; -+ -+ grub_memset(ctrl, 0, sizeof(*ctrl)); -+ -+ ctrl->reg = reg; -+ ctrl->pci = dev; -+ -+ if (grub_nvme_controller_enable(ctrl)) -+ goto err_free_ctrl; -+ -+ return 0; -+ -+ err_free_ctrl: -+ grub_free(ctrl); -+ err: -+ grub_dprintf("nvme", "Failed to enable NVMe controller.\n"); -+ return 0; -+} -+ -+static int -+grub_nvme_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) -+{ -+ struct nvme_namespace *ns; -+ -+ if (pull != GRUB_DISK_PULL_NONE) -+ return 0; -+ -+ FOR_LIST_ELEMENTS(ns, grub_nvme_namespaces) -+ if (hook (ns->devname, hook_data)) -+ return 1; -+ -+ return 0; -+} -+ -+static grub_err_t -+grub_nvme_open (const char *name __attribute ((unused)), grub_disk_t disk __attribute ((unused))) -+{ -+ struct nvme_namespace *ns; -+ -+ FOR_LIST_ELEMENTS(ns, grub_nvme_namespaces) -+ if (grub_strcmp (ns->devname, name) == 0) -+ break; -+ -+ if (! ns) -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); -+ -+ disk->total_sectors = ns->lba_count; -+ disk->max_agglomerate = ns->max_req_size; -+ -+ disk->id = ns->nsnum; /* global id of the namespace */ -+ -+ disk->data = ns; -+ -+ return 0; -+} -+ -+static grub_err_t -+nvme_readwrite(struct nvme_namespace *ns, grub_disk_addr_t sector, grub_size_t num_sectors, char *buf, int write) -+{ -+ for (int i = 0; i < num_sectors;) { -+ grub_uint16_t blocks_remaining = num_sectors - i; -+ char *op_buf = buf + i * ns->block_size; -+ int blocks = nvme_prpl_xfer(ns, sector + i, op_buf, blocks_remaining, write); -+ if (blocks < 0) -+ return GRUB_ERR_IO; -+ i += blocks; -+ } -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_nvme_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t num_sectors, char *buf) -+{ -+ return nvme_readwrite((struct nvme_namespace *) disk->data, sector, num_sectors, buf, 0); -+} -+ -+static grub_err_t -+grub_nvme_write (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t num_sectors, const char *buf) -+{ -+ return nvme_readwrite((struct nvme_namespace *) disk->data, sector, num_sectors, buf, 1); -+} -+ -+static struct grub_disk_dev grub_nvme_dev = -+ { -+ .name = "nvme", -+ .id = GRUB_DISK_DEVICE_NVME_ID, -+ .disk_iterate = grub_nvme_iterate, -+ .disk_open = grub_nvme_open, -+ .disk_read = grub_nvme_read, -+ .disk_write = grub_nvme_write, -+ .next = 0 -+ }; -+ -+GRUB_MOD_INIT(nvme) -+{ -+ grub_stop_disk_firmware (); -+ grub_pci_iterate (grub_nvme_pci_probe, NULL); -+ grub_disk_dev_register (&grub_nvme_dev); -+} -+ -+GRUB_MOD_FINI(nvme) -+{ -+ grub_disk_dev_unregister (&grub_nvme_dev); -+} -diff --git a/include/grub/disk.h b/include/grub/disk.h -index fbf23df7f..186e76f0b 100644 ---- a/include/grub/disk.h -+++ b/include/grub/disk.h -@@ -52,6 +52,7 @@ enum grub_disk_dev_id - GRUB_DISK_DEVICE_UBOOTDISK_ID, - GRUB_DISK_DEVICE_XEN, - GRUB_DISK_DEVICE_OBDISK_ID, -+ GRUB_DISK_DEVICE_NVME_ID - }; - - struct grub_disk; --- -2.39.2 - |