All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 6/6] luks2: Support key derival via Argon2
From: Patrick Steinhardt @ 2020-02-20 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: Patrick Steinhardt, Daniel Kiper, gmazyland, leif, agraf, pjones,
	mjg59, phcoder
In-Reply-To: <cover.1582221462.git.ps@pks.im>

One addition with LUKS2 was support of the key derival function Argon2
in addition to the previously supported PBKDF2 algortihm. In order to
ease getting in initial support for LUKS2, we only reused infrastructure
to support LUKS2 with PBKDF2, but left out Argon2.

This commit now introduces support for Argon2 to enable decryption of
LUKS2 partitions using this key derival function. As the code for Argon2
has been added in a previous commit in this series, adding support is
now trivial.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 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 94336392b..a50effce4 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 7e96cb1ce..7ffd26528 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1204,7 +1204,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 767631198..3c79f14aa 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>
 
@@ -435,8 +436,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.25.1



^ permalink raw reply related

* [PATCH v2 3/6] argon2: Import Argon2 from cryptsetup
From: Patrick Steinhardt @ 2020-02-20 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: Patrick Steinhardt, Daniel Kiper, gmazyland, leif, agraf, pjones,
	mjg59, phcoder
In-Reply-To: <cover.1582221462.git.ps@pks.im>

In order to support the Argon2 key derival function for LUKS2, we
obviously need to implement Argon2. It doesn't make a lot of sense to
hand-code any crypto, which is why this commit instead imports Argon2
from the cryptsetup project. This commit thus imports the code from the
official reference implementation located at [1]. The code is licensed
under CC0 1.0 Universal/Apache 2.0. Given that both LGPLv2.1+ and Apache
2.0 are compatible with GPLv3, it should be fine to import that code.

The code is imported from commit 62358ba (Merge pull request #270 from
bitmark-property-system/master, 2019-05-20). To make it work for GRUB,
several adjustments were required that have beed documented in
"grub-dev.texi".

[1]: https://github.com/P-H-C/phc-winner-argon2

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 docs/grub-dev.texi                            |  64 +++
 grub-core/Makefile.core.def                   |   8 +
 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                   | 525 ++++++++++++++++++
 grub-core/lib/argon2/core.h                   | 228 ++++++++
 grub-core/lib/argon2/ref.c                    | 190 +++++++
 11 files changed, 2195 insertions(+)
 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 df2350be0..490af8b01 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -489,10 +489,74 @@ GRUB includes some code from other projects, and it is sometimes necessary
 to update it.
 
 @menu
+* Argon2::
 * Gnulib::
 * jsmn::
 @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 a0507a1fa..7e96cb1ce 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1181,6 +1181,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/argon2.c b/grub-core/lib/argon2/argon2.c
new file mode 100644
index 000000000..c77f7f6ff
--- /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 ("GPLv3");
+
+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..1bb8e22e2
--- /dev/null
+++ b/grub-core/lib/argon2/core.c
@@ -0,0 +1,525 @@
+/*
+ * 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)
+
+/* for explicit_bzero() on glibc */
+#define _DEFAULT_SOURCE
+
+#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);
+    }
+}
+
+#if defined(__OpenBSD__)
+#define HAVE_EXPLICIT_BZERO 1
+#elif defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+#if __GLIBC_PREREQ(2,25)
+#define HAVE_EXPLICIT_BZERO 1
+#endif
+#endif
+
+void NOT_OPTIMIZED secure_wipe_memory(void *v, grub_size_t n) {
+#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
+    SecureZeroMemory(v, n);
+#elif defined grub_memset_s
+    grub_memset_s(v, n, 0, n);
+#elif defined(HAVE_EXPLICIT_BZERO)
+    explicit_bzero(v, n);
+#else
+    static void *(*const volatile grub_memset_sec)(void *, int, grub_size_t) = &grub_memset;
+    grub_memset_sec(v, 0, n);
+#endif
+}
+
+/* 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_uint32_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 */
+    absolute_position = (start_position + relative_position) %
+                        instance->lane_length; /* 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..d1f4134b3
--- /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 */
+        ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+        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.25.1



^ permalink raw reply related

* Re: [PATCH kvmtool v2] Add emulation for CFI compatible flash memory
From: Andre Przywara @ 2020-02-20 18:00 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: Raphael Gault, Sami Mujawar, Will Deacon, kvmarm,
	linux-arm-kernel
In-Reply-To: <9f51ac2e-c9a3-ef99-2d6a-2e31c4d5aa1c@arm.com>

On Thu, 20 Feb 2020 10:24:13 +0000
Alexandru Elisei <alexandru.elisei@arm.com> wrote:

Hi,

> On 2/19/20 5:26 PM, Andre Przywara wrote:
> > On Mon, 17 Feb 2020 17:20:43 +0000
> > Alexandru Elisei <alexandru.elisei@arm.com> wrote:
> >
> > Hi,
> >  
> >> I guess the device hasn't been tested with Linux. This is what I'm getting when
> >> trying to boot a Linux guest using the command:  
> > It was actually developed with a Linux guest, because that's more verbatim and easier to debug.
> >
> > And I just tested this again with Linux and it worked for me:  
> 
> The flash image you provided is 2 MB. The flash image that I used is 10 MB (it
> shows in the log that I sent). I guess you ran a different test.

What I stated below ... I guess there is some miscommunication here: I tested with Linux, just not with odd flash sizes. Which I agree should be either handled correctly or denied by kvmtool.

> 
> > [    2.164992] physmap-flash 20000.flash: physmap platform flash device: [mem 0x00020000-0x0021ffff]
> > [    2.166539] 20000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x00ffff
> > ...
> > # mtd_debug info /dev/mtd0
> > mtd.type = MTD_NORFLASH
> > mtd.flags = MTD_CAP_NORFLASH
> > mtd.size = 2097152 (2M)
> > mtd.erasesize = 65536 (64K)
> > mtd.writesize = 1 
> > mtd.oobsize = 0 
> > regions = 1
> >
> > I think what you are seeing are problems when you give a non-power-of-2 sized flash image. The current patch does not really support this (since it's hardly a thing in the real world). I originally wanted to expand any "uneven" size to the next power-of-2, but this doesn't work easily with mmap.  
> 
> I would expect that if kvmtool allows the user to specify a non-power-of-2 flash
> image size, then it should know how to deal with it and not present a broken
> device to a linux guest if that size is forbidden by the spec. Or it is allowed by
> the specification and kvmtool doesn't know how to deal with it?

I don't know, I would guess physical flash has always a power-of-2 size, at least on a per-chip base. So the "spec" doesn't even consider the other case.

> Instead of expanding the file provided by the user to fit a bigger flash, how
> about you use the highest power of two size that is smaller than the flash size?

The original idea was to avoid cutting off the flash file, but this doesn't really work easily, or at least is not worth the effort.
So I was suggesting the trimming you mentioned in the next sentence ;-)
                                                      vvvvvvvvvvvvv

> > So I now changed the code to downgrade, so you get 8MB with any file ranging from [8MB, 16MB(, for instance.
> > That fixed the Linux problems with those files for me.
> >  
> >> $ ./lkvm run -c4 -m4096 -k /path/to/kernel -d /path/to/disk -p root="/dev/vda2" -F
> >> flash.img
> >>
> >> [    0.659167] physmap-flash 2000000.flash: physmap platform flash device: [mem
> >> 0x02000000-0x029fffff]
> >> [    0.660444] Number of erase regions: 1
> >> [    0.661036] Primary Vendor Command Set: 0001 (Intel/Sharp Extended)
> >> [    0.661688] Primary Algorithm Table at 0031
> >> [    0.662168] Alternative Vendor Command Set: 0000 (None)
> >> [    0.662711] No Alternate Algorithm Table
> >> [    0.663120] Vcc Minimum:  4.5 V
> >> [    0.663450] Vcc Maximum:  5.5 V
> >> [    0.663779] No Vpp line
> >> [    0.664039] Typical byte/word write timeout: 2 µs
> >> [    0.664590] Maximum byte/word write timeout: 2 µs
> >> [    0.665240] Typical full buffer write timeout: 2 µs
> >> [    0.665775] Maximum full buffer write timeout: 2 µs
> >> [    0.666373] Typical block erase timeout: 2 ms
> >> [    0.666828] Maximum block erase timeout: 2 ms
> >> [    0.667282] Chip erase not supported
> >> [    0.667659] Device size: 0x800000 bytes (8 MiB)
> >> [    0.668137] Flash Device Interface description: 0x0006
> >> [    0.668697]   - Unknown
> >> [    0.668963] Max. bytes in buffer write: 0x40
> >> [    0.669407] Number of Erase Block Regions: 1
> >> [    0.669865]   Erase Region #0: BlockSize 0x8000 bytes, 160 blocks
> >> [    0.672299] 2000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank.
> >> Manufacturer ID 0x000000 Chip ID 0x00ffff
> >> [    0.681328] NOR chip too large to fit in mapping. Attempting to cope...
> >> [    0.682046] Intel/Sharp Extended Query Table at 0x0031
> >> [    0.682645] Using buffer write method
> >> [    0.683031] Sum of regions (a00000) != total size of set of interleaved chips
> >> (1000000)
> >> [    0.683854] gen_probe: No supported Vendor Command Set found
> >> [    0.684441] physmap-flash 2000000.flash: map_probe failed
> >>
> >> I also defined DEBUG_CFI in drivers/mtd/chips/cfi_probe.c.
> >>
> >> The Flash Device Interface description that we provide is wrong, it should 0x05.
> >> More details below.
> >>
> >> On 2/7/20 12:19 PM, Andre Przywara wrote:  
> >>> From: Raphael Gault <raphael.gault@arm.com>
> >>>
> >>> The EDK II UEFI firmware implementation requires some storage for the EFI
> >>> variables, which is typically some flash storage.
> >>> Since this is already supported on the EDK II side, we add a CFI flash
> >>> emulation to kvmtool.
> >>> This is backed by a file, specified via the --flash or -F command line
> >>> option. Any flash writes done by the guest will immediately be reflected
> >>> into this file (kvmtool mmap's the file).
> >>>
> >>> This implements a CFI flash using the "Intel/Sharp extended command
> >>> set", as specified in:
> >>> - JEDEC JESD68.01
> >>> - JEDEC JEP137B
> >>> - Intel Application Note 646
> >>> Some gaps in those specs have been filled by looking at real devices and
> >>> other implementations (QEMU, Linux kernel driver).
> >>>
> >>> At the moment this relies on DT to advertise the base address of the
> >>> flash memory (mapped into the MMIO address space) and is only enabled
> >>> for ARM/ARM64. The emulation itself is architecture agnostic, though.
> >>>
> >>> This is one missing piece toward a working UEFI boot with kvmtool on
> >>> ARM guests, the other is to provide writable PCI BARs, which is WIP.
> >>>
> >>> Signed-off-by: Raphael Gault <raphael.gault@arm.com>
> >>> [Andre: rewriting and fixing]
> >>> Signed-off-by: Andre Przywra <andre.przywara@arm.com>
> >>> ---
> >>> Hi,
> >>>
> >>> an update addressing Will's comments. I added coarse grained locking
> >>> to the MMIO handler, to prevent concurrent vCPU accesses from messing up
> >>> the internal CFI flash state machine.
> >>> I also folded the actual flash array read access into the MMIO handler
> >>> and fixed the other small issues.
> >>>
> >>> Cheers,
> >>> Andre
> >>>
> >>>  Makefile                          |   6 +
> >>>  arm/include/arm-common/kvm-arch.h |   3 +
> >>>  builtin-run.c                     |   2 +
> >>>  hw/cfi_flash.c                    | 546 ++++++++++++++++++++++++++++++
> >>>  include/kvm/kvm-config.h          |   1 +
> >>>  include/kvm/util.h                |   5 +
> >>>  6 files changed, 563 insertions(+)
> >>>  create mode 100644 hw/cfi_flash.c
> >>>
> >>> diff --git a/Makefile b/Makefile
> >>> index 3862112c..7ed6fb5e 100644
> >>> --- a/Makefile
> >>> +++ b/Makefile
> >>> @@ -170,6 +170,7 @@ ifeq ($(ARCH), arm)
> >>>  	CFLAGS		+= -march=armv7-a
> >>>  
> >>>  	ARCH_WANT_LIBFDT := y
> >>> +	ARCH_HAS_FLASH_MEM := y
> >>>  endif
> >>>  
> >>>  # ARM64
> >>> @@ -182,6 +183,7 @@ ifeq ($(ARCH), arm64)
> >>>  	ARCH_INCLUDE	+= -Iarm/aarch64/include
> >>>  
> >>>  	ARCH_WANT_LIBFDT := y
> >>> +	ARCH_HAS_FLASH_MEM := y
> >>>  endif
> >>>  
> >>>  ifeq ($(ARCH),mips)
> >>> @@ -261,6 +263,10 @@ ifeq (y,$(ARCH_HAS_FRAMEBUFFER))
> >>>  	endif
> >>>  endif
> >>>  
> >>> +ifeq (y,$(ARCH_HAS_FLASH_MEM))
> >>> +	OBJS	+= hw/cfi_flash.o
> >>> +endif
> >>> +
> >>>  ifeq ($(call try-build,$(SOURCE_ZLIB),$(CFLAGS),$(LDFLAGS) -lz),y)
> >>>  	CFLAGS_DYNOPT	+= -DCONFIG_HAS_ZLIB
> >>>  	LIBS_DYNOPT	+= -lz
> >>> diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
> >>> index b9d486d5..2bb085f4 100644
> >>> --- a/arm/include/arm-common/kvm-arch.h
> >>> +++ b/arm/include/arm-common/kvm-arch.h
> >>> @@ -21,6 +21,9 @@
> >>>  #define ARM_GIC_DIST_SIZE	0x10000
> >>>  #define ARM_GIC_CPUI_SIZE	0x20000
> >>>  
> >>> +#define ARM_FLASH_MMIO_BASE	0x2000000		/* 32 MB */
> >>> +#define KVM_FLASH_MMIO_BASE	ARM_FLASH_MMIO_BASE
> >>> +
> >>>  #define ARM_IOPORT_SIZE		(ARM_MMIO_AREA - ARM_IOPORT_AREA)
> >>>  #define ARM_VIRTIO_MMIO_SIZE	(ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
> >>>  #define ARM_PCI_CFG_SIZE	(1ULL << 24)
> >>> diff --git a/builtin-run.c b/builtin-run.c
> >>> index f8dc6c72..df8c6741 100644
> >>> --- a/builtin-run.c
> >>> +++ b/builtin-run.c
> >>> @@ -138,6 +138,8 @@ void kvm_run_set_wrapper_sandbox(void)
> >>>  			"Kernel command line arguments"),		\
> >>>  	OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\
> >>>  			"Firmware image to boot in virtual machine"),	\
> >>> +	OPT_STRING('F', "flash", &(cfg)->flash_filename, "flash",\
> >>> +			"Flash image to present to virtual machine"),	\
> >>>  									\
> >>>  	OPT_GROUP("Networking options:"),				\
> >>>  	OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params",	\
> >>> diff --git a/hw/cfi_flash.c b/hw/cfi_flash.c
> >>> new file mode 100644
> >>> index 00000000..d7c0e7e8
> >>> --- /dev/null
> >>> +++ b/hw/cfi_flash.c
> >>> @@ -0,0 +1,546 @@
> >>> +#include <stdbool.h>
> >>> +#include <stdlib.h>
> >>> +#include <string.h>
> >>> +#include <linux/bitops.h>
> >>> +#include <linux/err.h>
> >>> +#include <linux/sizes.h>
> >>> +#include <linux/types.h>
> >>> +
> >>> +#include "kvm/kvm.h"
> >>> +#include "kvm/kvm-arch.h"
> >>> +#include "kvm/devices.h"
> >>> +#include "kvm/fdt.h"
> >>> +#include "kvm/mutex.h"
> >>> +#include "kvm/util.h"
> >>> +
> >>> +/* The EDK2 driver hardcodes two 16-bit chips on a 32-bit bus. */
> >>> +#define CFI_NR_FLASH_CHIPS			2
> >>> +
> >>> +/* We always emulate a 32 bit bus width. */
> >>> +#define CFI_BUS_WIDTH				4
> >>> +
> >>> +/* The *effective* size of an erase block (over all chips) */
> >>> +#define FLASH_BLOCK_SIZE			SZ_64K
> >>> +
> >>> +#define PROGRAM_BUFF_SIZE_BITS			7
> >>> +#define PROGRAM_BUFF_SIZE			(1U << PROGRAM_BUFF_SIZE_BITS)
> >>> +
> >>> +/* CFI commands */
> >>> +#define CFI_CMD_LOCK_BLOCK			0x01
> >>> +#define CFI_CMD_ALTERNATE_WORD_PROGRAM_SETUP	0x10
> >>> +#define CFI_CMD_BLOCK_ERASE_SETUP		0x20
> >>> +#define CFI_CMD_WORD_PROGRAM_SETUP		0x40
> >>> +#define CFI_CMD_CLEAR_STATUS_REGISTER		0x50
> >>> +#define CFI_CMD_LOCK_BLOCK_SETUP		0x60
> >>> +#define CFI_CMD_READ_STATUS_REGISTER		0x70
> >>> +#define CFI_CMD_READ_JEDEC			0x90
> >>> +#define CFI_CMD_READ_CFI_QUERY			0x98
> >>> +#define CFI_CMD_BUFFERED_PROGRAM_CONFIRM	0xd0
> >>> +#define CFI_CMD_BLOCK_ERASE_CONFIRM		0xd0
> >>> +#define CFI_CMD_UNLOCK_BLOCK			0xd0
> >>> +#define CFI_CMD_BUFFERED_PROGRAM_SETUP		0xe8
> >>> +#define CFI_CMD_READ_ARRAY			0xff
> >>> +
> >>> +/*
> >>> + * CFI query table contents, as far as it is constant.
> >>> + */
> >>> +#define CFI_GEOM_OFFSET				0x27
> >>> +static u8 cfi_query_table[] = {
> >>> +		/* offset 0x10: CFI query identification string */
> >>> +	'Q', 'R', 'Y',		/* ID string */
> >>> +	0x01, 0x00,		/* primary command set: Intel/Sharp extended */
> >>> +	0x31, 0x00,		/* address of primary extended query table */
> >>> +	0x00, 0x00,		/* alternative command set: unused */
> >>> +	0x00, 0x00,		/* address of alternative extended query table*/
> >>> +		/* offset 0x1b: system interface information */
> >>> +	0x45,			/* minimum Vcc voltage: 4.5V */
> >>> +	0x55,			/* maximum Vcc voltage: 5.5V */
> >>> +	0x00,			/* minimum Vpp voltage: 0.0V (unused) */
> >>> +	0x00,			/* maximum Vpp voltage: 0.0V *(unused) */
> >>> +	0x01,			/* timeout for single word program: 2 us */
> >>> +	0x01,			/* timeout for multi-byte program: 2 us */
> >>> +	0x01,			/* timeout for block erase: 2 ms */
> >>> +	0x00,			/* timeout for full chip erase: not supported */
> >>> +	0x00,			/* max timeout for single word program: 1x */
> >>> +	0x00,			/* max timeout for mulit-byte program: 1x */
> >>> +	0x00,			/* max timeout for block erase: 1x */
> >>> +	0x00,			/* max timeout for chip erase: not supported */
> >>> +		/* offset 0x27: flash geometry information */
> >>> +	0x00,			/* size in power-of-2 bytes, filled later */
> >>> +	0x06, 0x00,		/* interface description: 32 and 16 bits */    
> >> I don't think this is correct. From Intel StrataFlash Embedded Memory (P30)
> >> Family, table 34:
> >>
> >> ""n" such that n+1 specifies the bit field that represents the flash device width
> >> capabilities as described in the table".  
> > Yeah, seems to be correct, but it looks this Intel Strata document is the only place which details this encoding (which looks like being retrofit somehow).
> > And I didn't really use this document, because it's a manufacturer data sheet and not a specification.  
> 
> The device is in the list of specification you provided in the commit message.

Where? I only see JEP137B, JESD68-01 and Intel AN-646 in the list up there.

> I
> think it would make the reviewers' life a lot easier if you posted all the
> documentation that you used, and drop documentation that you didn't. Where did you
> get the value 0x06 from? That was the only document from where I could infer what
> it means, maybe I didn't dig deep enough.
> 
> > I will change it to 0x5, but for the records Linux worked even with 0x6 for me.  
> 
> I would say that in this case working != correct, because Linux 5.6-rc2 defines
> 0x05 as a x32/x16 interface, and 0x06 is undefined in the file that I mentioned in
> the previous reply. Did you check to see if the Linux driver recognized that
> interface type? Maybe it changed between versions. I also tried 0x00,0x00 for the
> interface description and Linux also worked.

I guess because the emulation doesn't really care about the access size (we use memcpy).
 
> Either way, I followed the trail of breadcrumbs starting at the comment for the
> define and I found this in Common Flash Memory Interface Specification release
> 2.0, Appendix:
> 
> "Note: April 2000 -x16/x32 devices will be represented by hex value 0005h as
> requested by Intel in order to make them more software friendly. Changes will be
> made to the CFI drivers so that a bit-wise switch is created to represent
> different data widths. [..] For example, if we take the description for an x16/x32
> device (0005h) and we convert that to binary we get 0101b. If we add one to this
> value we get a bit pattern that looks like this: 0110b. This bit-wise switch
> indicates that the device a x16/x32 device".
> 
> I guess the reason for the inconsistencies is that at some point it used to be
> different, but it was changed because Intel requested it.

Yeah, I found this one as well later.

> >> If you want to advertise 32 and 16 bit write capabilities, it should be 5 because
> >> 5+1=6. This is also the value that the Linux kernel checks for (see
> >> include/linux/mtd/cfi.h, define CFI_INTERFACE_X16_BY_X32_ASYNC"). 6 actually means
> >> 32, 16 and 8 bit accesses.
> >>
> >> This begs another question: why do we support both 16 and 32 bit accesses instead
> >> of supporting only 32 bit?  
> > Because we can, there is no reason to restrict this. I feel like we should be as capable as possible, especially since it's trivial to emulate.  
> 
> Makes sense.
> 
> >  
> >>> +	PROGRAM_BUFF_SIZE_BITS + 1 - CFI_NR_FLASH_CHIPS, 0x00,
> >>> +				/* number of multi-byte writes */    
> >> Shouldn't the comment be maximum number of bytes in the write buffer?  
> > Yes, possibly.
> >  
> >>> +	0x01,			/* one erase block region */
> >>> +	0x00, 0x00, 0x00, 0x00, /* number and size of erase blocks, filled */
> >>> +		/* offset 0x31: Intel primary algorithm extended query table */
> >>> +	'P', 'R', 'I',
> >>> +	'1', '0',		/* version 1.0 */
> >>> +	0xa0, 0x00, 0x00, 0x00, /* optional features: instant lock & pm-read */
> >>> +	0x00,			/* no functions after suspend */
> >>> +	0x01, 0x00,		/* only lock bit supported */
> >>> +	0x50,			/* best Vcc value: 5.0V */
> >>> +	0x00,			/* best Vpp value: 0.0V (unused) */
> >>> +	0x01,			/* number of protection register fields */
> >>> +	0x00, 0x00, 0x00, 0x00,	/* protection field 1 description */
> >>> +};    
> >> As an aside, I found it impossible to review the cfi_query_table array in its
> >> current form. This is how I wrote the array so I could read it. I also took the
> >> liberty to remove the offset when indexing the array, making read_cfi less error
> >> prone, in my opinion:  
> > Please don't post elaborate code sequences as a comment, especially not if it gets mangled (Thunderbird is annoyingly bad in this respect).  
> 
> I use Thunderbird and it showed fine for me, and I have sent large diffs before in
> replies and I got no complaints. I use the settings from
> Documentation/process/email-clients.rst.

Maybe it was a problem because (I guess) you copy&pasted the diff in?
Because I see a "...skipping..." line in there, bogus line breaks and all tabs were converted into spaces. Or there was some cocky mail server in the queue ;-)

Eventually I gave up with sending diffs other than for demonstration purposes through the Thunderbird editor because of various problems.
As a workaround you could try to save the email, fix it up with a proper editor (or insert the patch there), then send it via git send-email.
Or avoid sending patches this way at all ;-)


I will send v3 tomorrow morning after double checking that I didn't miss a comment.

Cheers,
Andre

> Thanks,
> Alex
> > I think I would have got what you mean by showing just one line ;-)
> >
> > Cheers,
> > Andre
> >  
> >> diff --git a/hw/cfi_flash.c b/hw/cfi_flash.c
> >> index d7c0e7e80d69..65a90e288be8 100644
> >> --- a/hw/cfi_flash.c
> >> +++ b/hw/cfi_flash.c
> >> @@ -46,45 +46,43 @@
> >>   */
> >>  #define CFI_GEOM_OFFSET                                0x27
> >>  static u8 cfi_query_table[] = {
> >> -               /* offset 0x10: CFI query identification string */
> >> -       'Q', 'R', 'Y',          /* ID string */
> >> -       0x01, 0x00,             /* primary command set: Intel/Sharp extended */
> >> -       0x31, 0x00,             /* address of primary extended query table */
> >> -       0x00, 0x00,             /* alternative command set: unused */
> >> -       0x00, 0x00,             /* address of alternative extended query table*/
> >> -               /* offset 0x1b: system interface information */
> >> -       0x45,                   /* minimum Vcc voltage: 4.5V */
> >> -       0x55,                   /* maximum Vcc voltage: 5.5V */
> >> -       0x00,                   /* minimum Vpp voltage: 0.0V (unused) */
> >> -       0x00,                   /* maximum Vpp voltage: 0.0V *(unused) */
> >> -       0x01,                   /* timeout for single word program: 2 us */
> >> -       0x01,                   /* timeout for multi-byte program: 2 us */
> >> -       0x01,                   /* timeout for block erase: 2 ms */
> >> -       0x00,                   /* timeout for full chip erase: not supported */
> >> -       0x00,                   /* max timeout for single word program: 1x */
> >> -       0x00,                   /* max timeout for mulit-byte program: 1x */
> >> -       0x00,                   /* max timeout for block erase: 1x */
> >> -       0x00,                   /* max timeout for chip erase: not supported */
> >> -               /* offset 0x27: flash geometry information */
> >> -       0x00,                   /* size in power-of-2 bytes, filled later */
> >> -       0x06, 0x00,             /* interface description: 32 and 16 bits */
> >> -       PROGRAM_BUFF_SIZE_BITS + 1 - CFI_NR_FLASH_CHIPS, 0x00,
> >> +       [0x10] = 'Q', 'R', 'Y', /* ID string */
> >> +       [0x13] = 0x01, 0x00,    /* primary command set: Intel/Sharp extended */
> >> +       [0x15] = 0x31, 0x00,    /* address of primary extended query table */
> >> +       [0x17] = 0x00, 0x00,    /* alternative command set: unused */
> >> +       [0x19] = 0x00, 0x00,    /* address of alternative extended query table*/
> >> +       /* System interface information */
> >> +       [0x1b] = 0x45,          /* minimum Vcc voltage: 4.5V */
> >> +       [0x1c] = 0x55,          /* maximum Vcc voltage: 5.5V */
> >> +       [0x1d] = 0x00,          /* minimum Vpp voltage: 0.0V (unused) */
> >> +       [0x1e] = 0x00,          /* maximum Vpp voltage: 0.0V *(unused) */
> >> +       [0x1f] = 0x01,          /* timeout for single word program: 2 us */
> >> +       [0x20] = 0x01,          /* timeout for multi-byte program: 2 us */
> >> +       [0x21] = 0x01,          /* timeout for block erase: 2 ms */
> >> +       [0x22] = 0x00,          /* timeout for full chip erase: not supported */
> >> +       [0x23] = 0x00,          /* max timeout for single word program: 1x */
> >> +       [0x24] = 0x00,          /* max timeout for mulit-byte program: 1x */
> >> +       [0x25] = 0x00,          /* max timeout for block erase: 1x */
> >> +       [0x26] = 0x00,          /* max timeout for chip erase: not supported */
> >> +       /* Flash geometry information */
> >> +       [0x27] = 0x00,          /* size in power-of-2 bytes, filled later */
> >> +       [0x28] = 0x06, 0x00,    /* interface description: 32 and 16 bits */
> >> +       [0x2a] = PROGRAM_BUFF_SIZE_BITS + 1 - CFI_NR_FLASH_CHIPS, 0x00,
> >>                                 /* number of multi-byte writes */
> >> -       0x01,                   /* one erase block region */
> >> -       0x00, 0x00, 0x00, 0x00, /* number and size of erase blocks, filled */
> >> -               /* offset 0x31: Intel primary algorithm extended query table */
> >> -       'P', 'R', 'I',
> >> -       '1', '0',               /* version 1.0 */
> >> -       0xa0, 0x00, 0x00, 0x00, /* optional features: instant lock & pm-read */
> >> -       0x00,                   /* no functions after suspend */
> >> -       0x01, 0x00,             /* only lock bit supported */
> >> -       0x50,                   /* best Vcc value: 5.0V */
> >> -       0x00,                   /* best Vpp value: 0.0V (unused) */
> >> -       0x01,                   /* number of protection register fields */
> >> -       0x00, 0x00, 0x00, 0x00, /* protection field 1 description */
> >> +       [0x2c] = 0x01,          /* one erase block region */
> >> +       [0x2d] = 0x00, 0x00, 0x00, 0x00, /* number and size of erase blocks, filled */
> >> +       /* Intel primary algorithm extended query table */
> >> +       [0x31] = 'P', 'R', 'I', /* ID string */
> >> +       [0x34] = '1', '0',      /* version 1.0 */
> >> +       [0x36] = 0xa0, 0x00, 0x00, 0x00, /* optional features: instant lock &
> >> pm-read */
> >> +       [0x40] = 0x00,          /* no functions after suspend */
> >> +       [0x41] = 0x01, 0x00,    /* only lock bit supported */
> >> ...skipping...
> >> +       [0x10] = 'Q', 'R', 'Y', /* ID string */
> >> +       [0x13] = 0x01, 0x00,    /* primary command set: Intel/Sharp extended */
> >> +       [0x15] = 0x31, 0x00,    /* address of primary extended query table */
> >> +       [0x17] = 0x00, 0x00,    /* alternative command set: unused */
> >> +       [0x19] = 0x00, 0x00,    /* address of alternative extended query table*/
> >> +       /* System interface information */
> >> +       [0x1b] = 0x45,          /* minimum Vcc voltage: 4.5V */
> >> +       [0x1c] = 0x55,          /* maximum Vcc voltage: 5.5V */
> >> +       [0x1d] = 0x00,          /* minimum Vpp voltage: 0.0V (unused) */
> >> +       [0x1e] = 0x00,          /* maximum Vpp voltage: 0.0V *(unused) */
> >> +       [0x1f] = 0x01,          /* timeout for single word program: 2 us */
> >> +       [0x20] = 0x01,          /* timeout for multi-byte program: 2 us */
> >> +       [0x21] = 0x01,          /* timeout for block erase: 2 ms */
> >> +       [0x22] = 0x00,          /* timeout for full chip erase: not supported */
> >> +       [0x23] = 0x00,          /* max timeout for single word program: 1x */
> >> +       [0x24] = 0x00,          /* max timeout for mulit-byte program: 1x */
> >> +       [0x25] = 0x00,          /* max timeout for block erase: 1x */
> >> +       [0x26] = 0x00,          /* max timeout for chip erase: not supported */
> >> +       /* Flash geometry information */
> >> +       [0x27] = 0x00,          /* size in power-of-2 bytes, filled later */
> >> +       [0x28] = 0x06, 0x00,    /* interface description: 32 and 16 bits */
> >> +       [0x2a] = PROGRAM_BUFF_SIZE_BITS + 1 - CFI_NR_FLASH_CHIPS, 0x00,
> >>                                 /* number of multi-byte writes */
> >> -       0x01,                   /* one erase block region */
> >> -       0x00, 0x00, 0x00, 0x00, /* number and size of erase blocks, filled */
> >> -               /* offset 0x31: Intel primary algorithm extended query table */
> >> -       'P', 'R', 'I',
> >> -       '1', '0',               /* version 1.0 */
> >> -       0xa0, 0x00, 0x00, 0x00, /* optional features: instant lock & pm-read */
> >> -       0x00,                   /* no functions after suspend */
> >> -       0x01, 0x00,             /* only lock bit supported */
> >> -       0x50,                   /* best Vcc value: 5.0V */
> >> -       0x00,                   /* best Vpp value: 0.0V (unused) */
> >> -       0x01,                   /* number of protection register fields */
> >> -       0x00, 0x00, 0x00, 0x00, /* protection field 1 description */
> >> +       [0x2c] = 0x01,          /* one erase block region */
> >> +       [0x2d] = 0x00, 0x00, 0x00, 0x00, /* number and size of erase blocks, filled */
> >> +       /* Intel primary algorithm extended query table */
> >> +       [0x31] = 'P', 'R', 'I', /* ID string */
> >> +       [0x34] = '1', '0',      /* version 1.0 */
> >> +       [0x36] = 0xa0, 0x00, 0x00, 0x00, /* optional features: instant lock &
> >> pm-read */
> >> +       [0x40] = 0x00,          /* no functions after suspend */
> >> +       [0x41] = 0x01, 0x00,    /* only lock bit supported */
> >> +       [0x43] = 0x50,          /* best Vcc value: 5.0V */
> >> +       [0x43] = 0x00,          /* best Vpp value: 0.0V (unused) */
> >> +       [0x44] = 0x01,          /* number of protection register fields */
> >> +       [0x45] = 0x00, 0x00, 0x00, 0x00,/* protection field 1 description */
> >>  };
> >>  
> >> -
> >>  /*
> >>   * Those states represent a subset of the CFI flash state machine.
> >>   */
> >> @@ -141,10 +139,7 @@ static int nr_erase_blocks(struct cfi_flash_device *sfdev)
> >>   */
> >>  static u8 read_cfi(struct cfi_flash_device *sfdev, u64 addr)
> >>  {
> >> -       if (addr < 0x10)                /* CFI information starts at 0x10 */
> >> -               return 0;
> >> -
> >> -       if (addr - 0x10 > sizeof(cfi_query_table)) {
> >> +       if (addr > sizeof(cfi_query_table)) {
> >>                 pr_debug("CFI query read access beyond the end of table");
> >>                 return 0;
> >>         }
> >> @@ -163,7 +158,7 @@ static u8 read_cfi(struct cfi_flash_device *sfdev, u64 addr)
> >>                 return ((FLASH_BLOCK_SIZE / 256 ) / CFI_NR_FLASH_CHIPS) >> 8;
> >>         }
> >>  
> >> -       return cfi_query_table[addr - 0x10];
> >> +       return cfi_query_table[addr];
> >>  }
> >>  
> >>  static bool block_is_locked(struct cfi_flash_device *sfdev, u64 addr)
> >>
> >> Thanks,
> >> Alex  
> >>> +
> >>> +
> >>> +/*
> >>> + * Those states represent a subset of the CFI flash state machine.
> >>> + */
> >>> +enum cfi_flash_state {
> >>> +	READY,
> >>> +	LOCK_SETUP,
> >>> +	WP_SETUP,
> >>> +	BP_SETUP,
> >>> +	BP_LOAD,
> >>> +	ERASE_SETUP,
> >>> +};
> >>> +
> >>> +/*
> >>> + * The device can be in several **Read** modes.
> >>> + * We don't implement the asynchronous burst mode.
> >>> + */
> >>> +enum cfi_read_mode {
> >>> +	READ_ARRAY,
> >>> +	READ_STATUS,
> >>> +	READ_DEVICE_ID,
> >>> +	READ_QUERY,
> >>> +};
> >>> +
> >>> +struct cfi_flash_device {
> >>> +	struct device_header	dev_hdr;
> >>> +	/* Protects the CFI state machine variables in this data structure. */
> >>> +	struct mutex		mutex;
> >>> +	u64			base_addr;
> >>> +	u32			size;
> >>> +
> >>> +	void			*flash_memory;
> >>> +	u8			program_buffer[PROGRAM_BUFF_SIZE * 4];
> >>> +	unsigned long		*lock_bm;
> >>> +	u64			last_address;
> >>> +	unsigned int		buff_written;
> >>> +	unsigned int		program_length;
> >>> +
> >>> +	enum cfi_flash_state	state;
> >>> +	enum cfi_read_mode	read_mode;
> >>> +	u16			rcr;
> >>> +	u8			sr;
> >>> +};
> >>> +
> >>> +static int nr_erase_blocks(struct cfi_flash_device *sfdev)
> >>> +{
> >>> +	return sfdev->size / FLASH_BLOCK_SIZE;
> >>> +}
> >>> +
> >>> +/*
> >>> + * CFI queries always deal with one byte of information, possibly mirrored
> >>> + * to other bytes on the bus. This is dealt with in the callers.
> >>> + * The address provided is the one for 8-bit addressing, and would need to
> >>> + * be adjusted for wider accesses.
> >>> + */
> >>> +static u8 read_cfi(struct cfi_flash_device *sfdev, u64 addr)
> >>> +{
> >>> +	if (addr < 0x10)		/* CFI information starts at 0x10 */
> >>> +		return 0;
> >>> +
> >>> +	if (addr - 0x10 > sizeof(cfi_query_table)) {
> >>> +		pr_debug("CFI query read access beyond the end of table");
> >>> +		return 0;
> >>> +	}
> >>> +
> >>> +	/* Fixup dynamic information in the geometry part of the table. */
> >>> +	switch (addr) {
> >>> +	case CFI_GEOM_OFFSET:		/* device size in bytes, power of two */
> >>> +		return pow2_size(sfdev->size / CFI_NR_FLASH_CHIPS);
> >>> +	case CFI_GEOM_OFFSET + 6:	/* number of erase blocks, minus one */
> >>> +		return (nr_erase_blocks(sfdev) - 1) & 0xff;
> >>> +	case CFI_GEOM_OFFSET + 7:
> >>> +		return (nr_erase_blocks(sfdev) - 1) >> 8;
> >>> +	case CFI_GEOM_OFFSET + 8:	/* erase block size, in units of 256 */
> >>> +		return ((FLASH_BLOCK_SIZE / 256 ) / CFI_NR_FLASH_CHIPS) & 0xff;
> >>> +	case CFI_GEOM_OFFSET + 9:
> >>> +		return ((FLASH_BLOCK_SIZE / 256 ) / CFI_NR_FLASH_CHIPS) >> 8;
> >>> +	}
> >>> +
> >>> +	return cfi_query_table[addr - 0x10];
> >>> +}
> >>> +
> >>> +static bool block_is_locked(struct cfi_flash_device *sfdev, u64 addr)
> >>> +{
> >>> +	int block_nr = addr / FLASH_BLOCK_SIZE;
> >>> +
> >>> +	return test_bit(block_nr, sfdev->lock_bm);
> >>> +}
> >>> +
> >>> +#define DEV_ID_MASK 0x7ff
> >>> +static u16 read_dev_id(struct cfi_flash_device *sfdev, u64 addr)
> >>> +{
> >>> +	switch ((addr & DEV_ID_MASK) / CFI_BUS_WIDTH) {
> >>> +	case 0x0:				/* vendor ID */
> >>> +		return 0x0000;
> >>> +	case 0x1:				/* device ID */
> >>> +		return 0xffff;
> >>> +	case 0x2:
> >>> +		return block_is_locked(sfdev, addr & ~DEV_ID_MASK);
> >>> +	case 0x5:
> >>> +		return sfdev->rcr;
> >>> +	default:			/* Ignore the other entries. */
> >>> +		return 0;
> >>> +	}
> >>> +}
> >>> +
> >>> +static void lock_block(struct cfi_flash_device *sfdev, u64 addr, bool lock)
> >>> +{
> >>> +	int block_nr = addr / FLASH_BLOCK_SIZE;
> >>> +
> >>> +	if (lock)
> >>> +		set_bit(block_nr, sfdev->lock_bm);
> >>> +	else
> >>> +		clear_bit(block_nr, sfdev->lock_bm);
> >>> +}
> >>> +
> >>> +static void word_program(struct cfi_flash_device *sfdev,
> >>> +			 u64 addr, void *data, int len)
> >>> +{
> >>> +	if (block_is_locked(sfdev, addr)) {
> >>> +		sfdev->sr |= 0x12;
> >>> +		return;
> >>> +	}
> >>> +
> >>> +	memcpy(sfdev->flash_memory + addr, data, len);
> >>> +}
> >>> +
> >>> +/* Reset the program buffer state to prepare for follow-up writes. */
> >>> +static void buffer_setup(struct cfi_flash_device *sfdev)
> >>> +{
> >>> +	memset(sfdev->program_buffer, 0, sizeof(sfdev->program_buffer));
> >>> +	sfdev->last_address = ~0ULL;
> >>> +	sfdev->buff_written = 0;
> >>> +}
> >>> +
> >>> +static bool buffer_program(struct cfi_flash_device *sfdev,
> >>> +			   u64 addr, void *buffer, int len)
> >>> +{
> >>> +	unsigned int buf_addr;
> >>> +
> >>> +	if (sfdev->buff_written >= sfdev->program_length)
> >>> +		return false;
> >>> +
> >>> +	/*
> >>> +	 * The first word written into the buffer after the setup command
> >>> +	 * happens to be the base address for the buffer.
> >>> +	 * All subsequent writes need to be within this address and this
> >>> +	 * address plus the buffer size, so keep this value around.
> >>> +	 */
> >>> +	if (sfdev->last_address == ~0ULL)
> >>> +		sfdev->last_address = addr;
> >>> +
> >>> +	if (addr < sfdev->last_address)
> >>> +		return false;
> >>> +	buf_addr = addr - sfdev->last_address;
> >>> +	if (buf_addr >= PROGRAM_BUFF_SIZE)
> >>> +		return false;
> >>> +
> >>> +	memcpy(sfdev->program_buffer + buf_addr, buffer, len);
> >>> +	sfdev->buff_written++;
> >>> +
> >>> +	return true;
> >>> +}
> >>> +
> >>> +static void buffer_confirm(struct cfi_flash_device *sfdev)
> >>> +{
> >>> +	if (block_is_locked(sfdev, sfdev->last_address)) {
> >>> +		sfdev->sr |= 0x12;
> >>> +		return;
> >>> +	}
> >>> +	memcpy(sfdev->flash_memory + sfdev->last_address,
> >>> +	       sfdev->program_buffer,
> >>> +	       sfdev->buff_written * sizeof(u32));
> >>> +}
> >>> +
> >>> +static void block_erase_confirm(struct cfi_flash_device *sfdev, u64 addr)
> >>> +{
> >>> +	if (block_is_locked(sfdev, addr)) {
> >>> +		sfdev->sr |= 0x12;
> >>> +		return;
> >>> +	}
> >>> +
> >>> +	memset(sfdev->flash_memory + addr, 0xFF, FLASH_BLOCK_SIZE);
> >>> +}
> >>> +
> >>> +static void cfi_flash_mmio(struct kvm_cpu *vcpu,
> >>> +			   u64 addr, u8 *data, u32 len, u8 is_write,
> >>> +			   void *context)
> >>> +{
> >>> +	struct cfi_flash_device *sfdev = context;
> >>> +	u64 faddr = addr - sfdev->base_addr;
> >>> +	u32 value;
> >>> +
> >>> +	if (!is_write) {
> >>> +		u16 cfi_value = 0;
> >>> +
> >>> +		mutex_lock(&sfdev->mutex);
> >>> +
> >>> +		switch (sfdev->read_mode) {
> >>> +		case READ_ARRAY:
> >>> +			/* just copy the requested bytes from the array */
> >>> +			memcpy(data, sfdev->flash_memory + faddr, len);
> >>> +			goto out_unlock;
> >>> +		case READ_STATUS:
> >>> +			cfi_value = sfdev->sr;
> >>> +			break;
> >>> +		case READ_DEVICE_ID:
> >>> +			cfi_value = read_dev_id(sfdev, faddr);
> >>> +			break;
> >>> +		case READ_QUERY:
> >>> +			cfi_value = read_cfi(sfdev, faddr / CFI_BUS_WIDTH);
> >>> +			break;
> >>> +		}
> >>> +		switch (len) {
> >>> +		case 1:
> >>> +			*data = cfi_value;
> >>> +			break;
> >>> +		case 8: memset(data + 4, 0, 4);
> >>> +			/* fall-through */
> >>> +		case 4:
> >>> +			if (CFI_NR_FLASH_CHIPS == 2)
> >>> +				memcpy(data + 2, &cfi_value, 2);
> >>> +			else
> >>> +				memset(data + 2, 0, 2);
> >>> +			/* fall-through */
> >>> +		case 2:
> >>> +			memcpy(data, &cfi_value, 2);
> >>> +			break;
> >>> +		default:
> >>> +			pr_debug("CFI flash: illegal access length %d for read mode %d",
> >>> +				 len, sfdev->read_mode);
> >>> +			break;
> >>> +		}
> >>> +
> >>> +		goto out_unlock;
> >>> +	}
> >>> +
> >>> +	if (len > 4) {
> >>> +		pr_info("CFI flash: MMIO %d-bit write access not supported",
> >>> +			 len * 8);
> >>> +		return;
> >>> +	}
> >>> +
> >>> +	memcpy(&value, data, len);
> >>> +
> >>> +	mutex_lock(&sfdev->mutex);
> >>> +
> >>> +	switch (sfdev->state) {
> >>> +	case READY:			/* handled below */
> >>> +		break;
> >>> +
> >>> +	case LOCK_SETUP:
> >>> +		switch (value & 0xff) {
> >>> +		case CFI_CMD_LOCK_BLOCK:
> >>> +			lock_block(sfdev, faddr, true);
> >>> +			sfdev->read_mode = READ_STATUS;
> >>> +			break;
> >>> +		case CFI_CMD_UNLOCK_BLOCK:
> >>> +			lock_block(sfdev, faddr, false);
> >>> +			sfdev->read_mode = READ_STATUS;
> >>> +			break;
> >>> +		default:
> >>> +			sfdev->sr |= 0x30;
> >>> +			break;
> >>> +		}
> >>> +		sfdev->state = READY;
> >>> +		goto out_unlock;
> >>> +
> >>> +	case WP_SETUP:
> >>> +		word_program(sfdev, faddr, data, len);
> >>> +		sfdev->read_mode = READ_STATUS;
> >>> +		sfdev->state = READY;
> >>> +		goto out_unlock;
> >>> +
> >>> +	case BP_LOAD:
> >>> +		if (buffer_program(sfdev, faddr, data, len))
> >>> +			goto out_unlock;
> >>> +
> >>> +		if ((value & 0xFF) == CFI_CMD_BUFFERED_PROGRAM_CONFIRM) {
> >>> +			buffer_confirm(sfdev);
> >>> +			sfdev->read_mode = READ_STATUS;
> >>> +		} else {
> >>> +			pr_debug("CFI flash: BP_LOAD: expected CONFIRM(0xd0), got 0x%x @ 0x%llx",
> >>> +				 value, faddr);
> >>> +			sfdev->sr |= 0x10;
> >>> +		}
> >>> +		sfdev->state = READY;
> >>> +		goto out_unlock;
> >>> +
> >>> +	case BP_SETUP:
> >>> +		sfdev->program_length = (value & 0xffff) + 1;
> >>> +		if (sfdev->program_length > PROGRAM_BUFF_SIZE / 4)
> >>> +			sfdev->program_length = PROGRAM_BUFF_SIZE / 4;
> >>> +		sfdev->state = BP_LOAD;
> >>> +		sfdev->read_mode = READ_STATUS;
> >>> +		goto out_unlock;
> >>> +
> >>> +	case ERASE_SETUP:
> >>> +		if ((value & 0xff) == CFI_CMD_BLOCK_ERASE_CONFIRM)
> >>> +			block_erase_confirm(sfdev, faddr);
> >>> +		else
> >>> +			sfdev->sr |= 0x30;
> >>> +
> >>> +		sfdev->state = READY;
> >>> +		sfdev->read_mode = READ_STATUS;
> >>> +		goto out_unlock;
> >>> +	}
> >>> +
> >>> +	/* write commands in READY state */
> >>> +	switch (value & 0xFF) {
> >>> +	case CFI_CMD_READ_JEDEC:
> >>> +		sfdev->read_mode = READ_DEVICE_ID;
> >>> +		break;
> >>> +	case CFI_CMD_READ_STATUS_REGISTER:
> >>> +		sfdev->read_mode = READ_STATUS;
> >>> +		break;
> >>> +	case CFI_CMD_READ_CFI_QUERY:
> >>> +		sfdev->read_mode = READ_QUERY;
> >>> +		break;
> >>> +	case CFI_CMD_CLEAR_STATUS_REGISTER:
> >>> +		sfdev->sr = 0x80;
> >>> +		break;
> >>> +	case CFI_CMD_WORD_PROGRAM_SETUP:
> >>> +	case CFI_CMD_ALTERNATE_WORD_PROGRAM_SETUP:
> >>> +		sfdev->state = WP_SETUP;
> >>> +		sfdev->read_mode = READ_STATUS;
> >>> +		break;
> >>> +	case CFI_CMD_LOCK_BLOCK_SETUP:
> >>> +		sfdev->state = LOCK_SETUP;
> >>> +		break;
> >>> +	case CFI_CMD_BLOCK_ERASE_SETUP:
> >>> +		sfdev->state = ERASE_SETUP;
> >>> +		sfdev->read_mode = READ_STATUS;
> >>> +		break;
> >>> +	case CFI_CMD_BUFFERED_PROGRAM_SETUP:
> >>> +		buffer_setup(sfdev);
> >>> +		sfdev->state = BP_SETUP;
> >>> +		sfdev->read_mode = READ_STATUS;
> >>> +		break;
> >>> +	case CFI_CMD_BUFFERED_PROGRAM_CONFIRM:
> >>> +		pr_debug("CFI flash: unexpected confirm command 0xD0");
> >>> +		break;
> >>> +	default:
> >>> +		pr_debug("CFI flash: unknown command 0x%x", value);
> >>> +		/* fall through */
> >>> +	case CFI_CMD_READ_ARRAY:
> >>> +		sfdev->read_mode = READ_ARRAY;
> >>> +		break;
> >>> +	}
> >>> +
> >>> +out_unlock:
> >>> +	mutex_unlock(&sfdev->mutex);
> >>> +}
> >>> +
> >>> +#ifdef CONFIG_HAS_LIBFDT
> >>> +static void generate_cfi_flash_fdt_node(void *fdt,
> >>> +					struct device_header *dev_hdr,
> >>> +					void (*generate_irq_prop)(void *fdt,
> >>> +								  u8 irq,
> >>> +								enum irq_type))
> >>> +{
> >>> +	struct cfi_flash_device *sfdev;
> >>> +	u64 reg_prop[2];
> >>> +
> >>> +	sfdev = container_of(dev_hdr, struct cfi_flash_device, dev_hdr);
> >>> +	reg_prop[0] = cpu_to_fdt64(sfdev->base_addr);
> >>> +	reg_prop[1] = cpu_to_fdt64(sfdev->size);
> >>> +
> >>> +	_FDT(fdt_begin_node(fdt, "flash"));
> >>> +	_FDT(fdt_property_cell(fdt, "bank-width", CFI_BUS_WIDTH));
> >>> +	_FDT(fdt_property_cell(fdt, "#address-cells", 0x1));
> >>> +	_FDT(fdt_property_cell(fdt, "#size-cells", 0x1));
> >>> +	_FDT(fdt_property_string(fdt, "compatible", "cfi-flash"));
> >>> +	_FDT(fdt_property_string(fdt, "label", "System-firmware"));
> >>> +	_FDT(fdt_property(fdt, "reg", &reg_prop, sizeof(reg_prop)));
> >>> +	_FDT(fdt_end_node(fdt));
> >>> +}
> >>> +#else
> >>> +#define generate_cfi_flash_fdt_node NULL
> >>> +#endif
> >>> +
> >>> +static struct cfi_flash_device *create_flash_device_file(struct kvm *kvm,
> >>> +							 const char *filename)
> >>> +{
> >>> +	struct cfi_flash_device *sfdev;
> >>> +	struct stat statbuf;
> >>> +	unsigned int value;
> >>> +	int ret;
> >>> +	int fd;
> >>> +
> >>> +	fd = open(filename, O_RDWR);
> >>> +	if (fd < 0)
> >>> +		return ERR_PTR(-errno);
> >>> +	if (fstat(fd, &statbuf) < 0) {
> >>> +		close(fd);
> >>> +		return ERR_PTR(-errno);
> >>> +	}
> >>> +
> >>> +	sfdev = malloc(sizeof(struct cfi_flash_device));
> >>> +	if (!sfdev) {
> >>> +		close(fd);
> >>> +		return ERR_PTR(-ENOMEM);
> >>> +	}
> >>> +
> >>> +	sfdev->size = (statbuf.st_size + 4095) & ~0xfffUL;
> >>> +	sfdev->flash_memory = mmap(NULL, statbuf.st_size,
> >>> +				   PROT_READ | PROT_WRITE, MAP_SHARED,
> >>> +				   fd, 0);
> >>> +	if (sfdev->flash_memory == MAP_FAILED) {
> >>> +		close(fd);
> >>> +		free(sfdev);
> >>> +		return ERR_PTR(-errno);
> >>> +	}
> >>> +	sfdev->base_addr = KVM_FLASH_MMIO_BASE;
> >>> +	sfdev->state = READY;
> >>> +	sfdev->read_mode = READ_ARRAY;
> >>> +	sfdev->sr = 0x80;
> >>> +	sfdev->rcr = 0xbfcf;
> >>> +
> >>> +	value = roundup(nr_erase_blocks(sfdev), BITS_PER_LONG) / 8;
> >>> +	sfdev->lock_bm = malloc(value);
> >>> +	memset(sfdev->lock_bm, 0, value);
> >>> +
> >>> +	sfdev->dev_hdr.bus_type = DEVICE_BUS_MMIO;
> >>> +	sfdev->dev_hdr.data = generate_cfi_flash_fdt_node;
> >>> +	mutex_init(&sfdev->mutex);
> >>> +	ret = device__register(&sfdev->dev_hdr);
> >>> +	if (ret) {
> >>> +		free(sfdev->flash_memory);
> >>> +		free(sfdev);
> >>> +		return ERR_PTR(ret);
> >>> +	}
> >>> +
> >>> +	ret = kvm__register_mmio(kvm,
> >>> +				 sfdev->base_addr, sfdev->size,
> >>> +				 false, cfi_flash_mmio, sfdev);
> >>> +	if (ret) {
> >>> +		device__unregister(&sfdev->dev_hdr);
> >>> +		free(sfdev->flash_memory);
> >>> +		free(sfdev);
> >>> +		return ERR_PTR(ret);
> >>> +	}
> >>> +
> >>> +	return sfdev;
> >>> +}
> >>> +
> >>> +static int flash__init(struct kvm *kvm)
> >>> +{
> >>> +	struct cfi_flash_device *sfdev;
> >>> +
> >>> +	if (!kvm->cfg.flash_filename)
> >>> +		return 0;
> >>> +
> >>> +	sfdev = create_flash_device_file(kvm, kvm->cfg.flash_filename);
> >>> +	if (IS_ERR(sfdev))
> >>> +		return PTR_ERR(sfdev);
> >>> +
> >>> +	return 0;
> >>> +}
> >>> +dev_init(flash__init);
> >>> diff --git a/include/kvm/kvm-config.h b/include/kvm/kvm-config.h
> >>> index a052b0bc..f4a8b831 100644
> >>> --- a/include/kvm/kvm-config.h
> >>> +++ b/include/kvm/kvm-config.h
> >>> @@ -35,6 +35,7 @@ struct kvm_config {
> >>>  	const char *vmlinux_filename;
> >>>  	const char *initrd_filename;
> >>>  	const char *firmware_filename;
> >>> +	const char *flash_filename;
> >>>  	const char *console;
> >>>  	const char *dev;
> >>>  	const char *network;
> >>> diff --git a/include/kvm/util.h b/include/kvm/util.h
> >>> index 4ca7aa93..5c37f0b7 100644
> >>> --- a/include/kvm/util.h
> >>> +++ b/include/kvm/util.h
> >>> @@ -104,6 +104,11 @@ static inline unsigned long roundup_pow_of_two(unsigned long x)
> >>>  	return x ? 1UL << fls_long(x - 1) : 0;
> >>>  }
> >>>  
> >>> +static inline int pow2_size(unsigned long x)
> >>> +{
> >>> +	return (sizeof(x) * 8) - __builtin_clzl(x - 1);
> >>> +}
> >>> +
> >>>  struct kvm;
> >>>  void *mmap_hugetlbfs(struct kvm *kvm, const char *htlbfs_path, u64 size);
> >>>  void *mmap_anon_or_hugetlbfs(struct kvm *kvm, const char *hugetlbfs_path, u64 size);    

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply

* Re: [RESEND PATCH v2 0/2] Enable Odroid-XU3/4 to use Energy Model and Energy Aware Scheduler
From: Krzysztof Kozlowski @ 2020-02-20 18:00 UTC (permalink / raw)
  To: Lukasz Luba
  Cc: linux-kernel, kgene, linux-arm-kernel, linux-samsung-soc,
	devicetree, linux-pm, myungjoo.ham, kyungmin.park, cw00.choi,
	robh+dt, mark.rutland, b.zolnierkie, dietmar.eggemann
In-Reply-To: <20200220095636.29469-1-lukasz.luba@arm.com>

On Thu, Feb 20, 2020 at 09:56:34AM +0000, Lukasz Luba wrote:
> Hi all,
> 
> This is just a resend, now with proper v2 in the patches subject.
> 
> The Odroid-XU4/3 is a decent and easy accessible ARM big.LITTLE platform,
> which might be used for research and development.
> 
> This small patch set provides possibility to run Energy Aware Scheduler (EAS)
> on Odroid-XU4/3 and experiment with it. 
> 
> The patch 1/2 provides 'dynamic-power-coefficient' in CPU DT nodes, which is
> then used by the Energy Model (EM).
> The patch 2/2 enables SCHED_MC (which adds another level in scheduling domains)
> and enables EM making EAS possible to run (when schedutil is set as a CPUFreq
> governor).
> 
> 1. Test results
> 
> Two types of different tests have been executed. The first is energy test
> case showing impact on energy consumption of this patch set. It is using a
> synthetic set of tasks (rt-app based). The second is the performance test
> case which is using hackbench (less time to complete is better).
> In both tests schedutil has been used as cpufreq governor. In all tests
> PROVE_LOCKING has not been compiled into the kernels.
> 
> 1.1 Energy test case
> 
> 10 iterations of 24 periodic rt-app tasks (16ms period, 10% duty-cycle)
> with energy measurement. The cpufreq governor - schedutil. Unit is Joules.
> The energy is calculated based on hwmon0 and hwmon3 power1_input.
> The goal is to save energy, lower is better.
> 
> +-----------+-----------------+------------------------+
> |           | Without patches | With patches           |
> +-----------+--------+--------+----------------+-------+
> | benchmark |  Mean  | RSD*   | Mean           | RSD*  |
> +-----------+--------+--------+----------------+-------+
> | 24 rt-app |  21.56 |  1.37% |  19.85 (-9.2%) | 0.92% |
> |    tasks  |        |        |                |       |
> +-----------+--------+--------+----------------+-------+
> 
> 1.2 Performance test case
> 
> 10 consecutive iterations of hackbench (hackbench -l 500 -s 4096),
> no delay between two successive executions.
> The cpufreq governor - schedutil. Units in seconds.
> The goal is to see not regression, lower completion time is better.
> 
> +-----------+-----------------+------------------------+
> |           | Without patches | With patches           |
> +-----------+--------+--------+----------------+-------+
> | benchmark | Mean   | RSD*   | Mean           | RSD*  |
> +-----------+--------+--------+----------------+-------+
> | hackbench |  8.15  | 2.86%  |  7.95 (-2.5%)  | 0.60% |
> +-----------+--------+--------+----------------+-------+
> 
> *RSD: Relative Standard Deviation (std dev / mean)

Nice measurements!

Applied both, thank you.

Best regards,
Krzysztof


^ permalink raw reply

* [PATCH v2 5/6] luks2: Discern Argon2i and Argon2id
From: Patrick Steinhardt @ 2020-02-20 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: Patrick Steinhardt, Daniel Kiper, gmazyland, leif, agraf, pjones,
	mjg59, phcoder
In-Reply-To: <cover.1582221462.git.ps@pks.im>

While GRUB is already able to parse both Argon2i and Argon2id parameters
from the LUKS2 header, it doesn't discern both types. This commit
introduces a new KDF type for Argon2id and sets up the parsed KDF's type
accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 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 65c4f0aac..767631198 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -40,6 +40,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;
@@ -158,10 +159,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"))
@@ -432,6 +434,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.25.1



^ permalink raw reply related

* [PATCH v2 4/6] luks2: Add missing newline to debug message
From: Patrick Steinhardt @ 2020-02-20 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: Patrick Steinhardt, Daniel Kiper, gmazyland, leif, agraf, pjones,
	mjg59, phcoder
In-Reply-To: <cover.1582221462.git.ps@pks.im>

The debug message printed when decryption with a keyslot fails is
missing its trailing newline. Add it to avoid mangling it with
subsequent output.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/luks2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 49ee9c862..65c4f0aac 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -610,7 +610,7 @@ luks2_recover_key (grub_disk_t disk,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed", i);
+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed\n", i);
 	  continue;
 	}
 
-- 
2.25.1



^ permalink raw reply related

* Re: [PATCH] net: ip6_gre: Distribute switch variables for initialization
From: David Miller @ 2020-02-20 18:00 UTC (permalink / raw)
  To: keescook; +Cc: kuznet, yoshfuji, glider, netdev, linux-kernel
In-Reply-To: <20200220062307.68986-1-keescook@chromium.org>

From: Kees Cook <keescook@chromium.org>
Date: Wed, 19 Feb 2020 22:23:07 -0800

> Variables declared in a switch statement before any case statements
> cannot be automatically initialized with compiler instrumentation (as
> they are not part of any execution flow). With GCC's proposed automatic
> stack variable initialization feature, this triggers a warning (and they
> don't get initialized). Clang's automatic stack variable initialization
> (via CONFIG_INIT_STACK_ALL=y) doesn't throw a warning, but it also
> doesn't initialize such variables[1]. Note that these warnings (or silent
> skipping) happen before the dead-store elimination optimization phase,
> so even when the automatic initializations are later elided in favor of
> direct initializations, the warnings remain.
> 
> To avoid these problems, move such variables into the "case" where
> they're used or lift them up into the main function body.
> 
> net/ipv6/ip6_gre.c: In function ‘ip6gre_err’:
> net/ipv6/ip6_gre.c:440:32: warning: statement will never be executed [-Wswitch-unreachable]
>   440 |   struct ipv6_tlv_tnl_enc_lim *tel;
>       |                                ^~~
> 
> net/ipv6/ip6_tunnel.c: In function ‘ip6_tnl_err’:
> net/ipv6/ip6_tunnel.c:520:32: warning: statement will never be executed [-Wswitch-unreachable]
>   520 |   struct ipv6_tlv_tnl_enc_lim *tel;
>       |                                ^~~
> 
> [1] https://bugs.llvm.org/show_bug.cgi?id=44916
> 
> Signed-off-by: Kees Cook <keescook@chromium.org>

Applied.

^ permalink raw reply

* [PATCH v2 0/6] Support Argon2 KDF in LUKS2
From: Patrick Steinhardt @ 2020-02-20 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: Patrick Steinhardt, Daniel Kiper, gmazyland, leif, agraf, pjones,
	mjg59, phcoder
In-Reply-To: <cover.1580998938.git.ps@pks.im>

Hi,

this is the second version of my patchset to add support for Argon2
encryption keys for LUKS2.

The most important change is that I've now verbosely imported the argon2
code from the official reference implementation instead of from the
cryptsetup project. The diff between both isn't that big in the end, and
including from crypsetup's upstream seems a bit cleaner to me. There
were several transformations required to use GRUB's types and functions
as well as stripping of unused stuff, which I've now documented the dev
manual. This also fixes my previously mistaken license headers.

One thing I'm not sure about here is whether it's fine to declare the
argon2 mod's license as GPLv3. The code is licensed under CC0/Apache
2.0, where the latter is compatible with GPLv3. But I don't know whether
it's legit to just say "Yeah, this mod is a GPLv3 one".

I didn't address the comment made by Leif yet with regards to grabbing
memory. I ain't got much of a clue of GRUB's memory subsystem, so I'd
gladly accept help there. Otherwise I'll have to dig a bit deeper.

The range diff compared to the previous version of this patch set is
attached to this mail.

Patrick


Patrick Steinhardt (6):
  efi: Allocate half of available memory by default
  types.h: add UINT-related macros needed for Argon2
  argon2: Import Argon2 from cryptsetup
  luks2: Add missing newline to debug message
  luks2: Discern Argon2i and Argon2id
  luks2: Support key derival via Argon2

 Makefile.util.def                             |   6 +-
 docs/grub-dev.texi                            |  64 +++
 grub-core/Makefile.core.def                   |  10 +-
 grub-core/disk/luks2.c                        |  28 +-
 grub-core/kern/efi/mm.c                       |   4 +-
 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                   | 525 ++++++++++++++++++
 grub-core/lib/argon2/core.h                   | 228 ++++++++
 grub-core/lib/argon2/ref.c                    | 190 +++++++
 include/grub/types.h                          |   8 +
 15 files changed, 2231 insertions(+), 12 deletions(-)
 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

Range-diff against v1:
1:  53cdfdc27 = 1:  15bdf830e efi: Allocate half of available memory by default
2:  c55946ca5 < -:  --------- argon2: Import Argon2 from cryptsetup
-:  --------- > 2:  e81db7d95 types.h: add UINT-related macros needed for Argon2
-:  --------- > 3:  50aff9670 argon2: Import Argon2 from cryptsetup
3:  c17cd2197 ! 4:  af3f85665 disk: luks2: Add missing newline to debug message
    @@ Metadata
     Author: Patrick Steinhardt <ps@pks.im>
     
      ## Commit message ##
    -    disk: luks2: Add missing newline to debug message
    +    luks2: Add missing newline to debug message
     
         The debug message printed when decryption with a keyslot fails is
         missing its trailing newline. Add it to avoid mangling it with
         subsequent output.
     
         Signed-off-by: Patrick Steinhardt <ps@pks.im>
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
4:  390728cea ! 5:  89abe827b disk: luks2: Discern Argon2i and Argon2id
    @@ Metadata
     Author: Patrick Steinhardt <ps@pks.im>
     
      ## Commit message ##
    -    disk: luks2: Discern Argon2i and Argon2id
    +    luks2: Discern Argon2i and Argon2id
     
         While GRUB is already able to parse both Argon2i and Argon2id parameters
         from the LUKS2 header, it doesn't discern both types. This commit
5:  ec4389627 ! 6:  70a354e0b disk: luks2: Support key derival via Argon2
    @@ Metadata
     Author: Patrick Steinhardt <ps@pks.im>
     
      ## Commit message ##
    -    disk: luks2: Support key derival via Argon2
    +    luks2: Support key derival via Argon2
     
         One addition with LUKS2 was support of the key derival function Argon2
         in addition to the previously supported PBKDF2 algortihm. In order to
    @@ Makefile.util.def: library = {
        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;
    @@ grub-core/disk/luks2.c: luks2_decrypt_key (grub_uint8_t *out_key,
            case LUKS2_KDF_TYPE_ARGON2ID:
     -	ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Argon2 not supported");
     -	goto err;
    -+	ret = grub_crypto_argon2 (passphrase, passphraselen, salt, saltlen,
    -+				  k->kdf.u.argon2.time, k->kdf.u.argon2.memory, k->kdf.u.argon2.cpus,
    -+				  k->kdf.type == LUKS2_KDF_TYPE_ARGON2I ? GRUB_ARGON2_I : GRUB_ARGON2_ID,
    -+				  GRUB_ARGON2_VERSION_NUMBER,
    -+				  area_key, k->area.key_size);
    ++	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", grub_errmsg);
    ++	    grub_dprintf ("luks2", "Argon2 failed: %s\n", argon2_error_message (ret));
     +	    goto err;
     +	  }
     +        break;
-- 
2.25.1



^ permalink raw reply

* [PATCH v2 1/6] efi: Allocate half of available memory by default
From: Patrick Steinhardt @ 2020-02-20 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: Patrick Steinhardt, Daniel Kiper, gmazyland, leif, agraf, pjones,
	mjg59, phcoder
In-Reply-To: <cover.1582221462.git.ps@pks.im>

By default, GRUB will allocate a quarter of the pages it got available
in the EFI subsystem. On many current systems, this will amount to
roughly 800MB of RAM assuming an address space of 32 bits. This is
plenty for most use cases, but it doesn't suffice when using full disk
encryption with a key derival function based on Argon2.

Besides the usual iteration count known from PBKDF2, Argon2 introduces
two additional parameters "memory" and "parallelism". While the latter
doesn't really matter to us, the memory parameter is quite interesting.
If encrypting a partition with LUKS2 using Argon2 as KDF, then
cryptsetup will default to a memory parameter of 1GB. Meaning we need to
allocate a buffer of 1GB in size in order to be able to derive the key,
which definitely won't squeeze into the limit of 800MB.

To prepare for Argon2, let's thus increase the default and make half of
memory available, instead of a quarter only. This amounts to about
1600MB on above systems, which is sufficient for Argon2.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/kern/efi/mm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index b02fab1b1..d1f9d046b 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -599,10 +599,10 @@ grub_efi_mm_init (void)
   filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
 					       desc_size, memory_map_end);
 
-  /* By default, request a quarter of the available memory.  */
+  /* By default, request half of the available memory.  */
   total_pages = get_total_pages (filtered_memory_map, desc_size,
 				 filtered_memory_map_end);
-  required_pages = (total_pages >> 2);
+  required_pages = (total_pages / 2);
   if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
     required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
   else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
-- 
2.25.1



^ permalink raw reply related

* [PATCH v2 2/6] types.h: add UINT-related macros needed for Argon2
From: Patrick Steinhardt @ 2020-02-20 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: Patrick Steinhardt, Daniel Kiper, gmazyland, leif, agraf, pjones,
	mjg59, phcoder
In-Reply-To: <cover.1582221462.git.ps@pks.im>

For the upcoming import of the Argon2 library, we need the macros
GRUB_UINT32_MAX, GRUB_UINT32_C and GRUB_UINT64_C. Add them as a
preparatory step.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 include/grub/types.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/grub/types.h b/include/grub/types.h
index 035a4b528..35ba900dd 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -137,6 +137,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
@@ -151,6 +152,13 @@ typedef grub_int32_t	grub_ssize_t;
 #endif
 # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
 
+# 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.25.1



^ permalink raw reply related

* Re: [PATCH] net: core: Distribute switch variables for initialization
From: David Miller @ 2020-02-20 18:00 UTC (permalink / raw)
  To: keescook; +Cc: kuba, glider, netdev, linux-kernel
In-Reply-To: <20200220062304.68942-1-keescook@chromium.org>

From: Kees Cook <keescook@chromium.org>
Date: Wed, 19 Feb 2020 22:23:04 -0800

> Variables declared in a switch statement before any case statements
> cannot be automatically initialized with compiler instrumentation (as
> they are not part of any execution flow). With GCC's proposed automatic
> stack variable initialization feature, this triggers a warning (and they
> don't get initialized). Clang's automatic stack variable initialization
> (via CONFIG_INIT_STACK_ALL=y) doesn't throw a warning, but it also
> doesn't initialize such variables[1]. Note that these warnings (or silent
> skipping) happen before the dead-store elimination optimization phase,
> so even when the automatic initializations are later elided in favor of
> direct initializations, the warnings remain.
> 
> To avoid these problems, move such variables into the "case" where
> they're used or lift them up into the main function body.
> 
> net/core/skbuff.c: In function ‘skb_checksum_setup_ip’:
> net/core/skbuff.c:4809:7: warning: statement will never be executed [-Wswitch-unreachable]
>  4809 |   int err;
>       |       ^~~
> 
> [1] https://bugs.llvm.org/show_bug.cgi?id=44916
> 
> Signed-off-by: Kees Cook <keescook@chromium.org>

Applied.

^ permalink raw reply

* Re: [PATCH 1/4] drm/connector: Add data polarity flags
From: Maxime Ripard @ 2020-02-20 18:00 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Mark Rutland, devicetree, David Airlie, Maarten Lankhorst,
	dri-devel, Chen-Yu Tsai, Rob Herring, Sean Paul, Thierry Reding,
	Daniel Vetter, Frank Rowand, linux-arm-kernel
In-Reply-To: <20200214161359.GB18287@ravnborg.org>


[-- Attachment #1.1: Type: text/plain, Size: 1486 bytes --]

On Fri, Feb 14, 2020 at 05:13:59PM +0100, Sam Ravnborg wrote:
> Hi Maxime.
>
> On Fri, Feb 14, 2020 at 01:24:38PM +0100, Maxime Ripard wrote:
> > Some LVDS encoders can change the polarity of the data signals being
> > sent. Add a DRM bus flag to reflect this.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  include/drm/drm_connector.h | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> > index 221910948b37..9a08fe6ab7c2 100644
> > --- a/include/drm/drm_connector.h
> > +++ b/include/drm/drm_connector.h
> > @@ -330,6 +330,8 @@ enum drm_panel_orientation {
> >   *					edge of the pixel clock
> >   * @DRM_BUS_FLAG_SHARP_SIGNALS:		Set if the Sharp-specific signals
> >   *					(SPL, CLS, PS, REV) must be used
> > + * @DRM_BUS_FLAG_DATA_LOW:		The Data signals are active low
> > + * @DRM_BUS_FLAG_DATA_HIGH:		The Data signals are active high
> Reading the description of these falgs always confuses me.
> In this case if neither bit 9 nor bit 10 is set then the data signals
> are netiher active low nor active high.
> So what can I then expect?
>
> We have the same logic loophole for DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE
> and DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE.
> So it is not new, but can we do better here?

Honestly, I don't really get it either. I *think* this is to handle
the sampling / output inversion properly which wouldn't be possible if
this was only a bit set or not.

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 1/2] rtc: sun6i: Make external 32k oscillator optional
From: Jernej Škrabec @ 2020-02-20 17:59 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: mark.rutland, a.zummo, alexandre.belloni, devicetree,
	linux-kernel, wens, robh+dt, linux-arm-kernel, linux-rtc
In-Reply-To: <20200220174749.ih3pcj3oxiwvuurz@gilmour.lan>

Dne četrtek, 20. februar 2020 ob 18:47:49 CET je Maxime Ripard napisal(a):
> On Fri, Feb 14, 2020 at 05:42:13PM +0100, Jernej Škrabec wrote:
> > Hi Maxime,
> > 
> > Dne petek, 14. februar 2020 ob 09:14:43 CET je Maxime Ripard napisal(a):
> > > Hi Jernej,
> > > 
> > > Thanks for taking care of this
> > > 
> > > On Thu, Feb 13, 2020 at 10:14:26PM +0100, Jernej Skrabec wrote:
> > > > Some boards, like OrangePi PC2 (H5), OrangePi Plus 2E (H3) and Tanix
> > > > TX6
> > > > (H6) don't have external 32kHz oscillator. Till H6, it didn't really
> > > > matter if external oscillator was enabled because HW detected error
> > > > and
> > > > fall back to internal one. H6 has same functionality but it's the
> > > > first
> > > > SoC which have "auto switch bypass" bit documented and always enabled
> > > > in
> > > > driver. This prevents RTC to work correctly if external crystal is not
> > > > present on board. There are other side effects - all peripherals which
> > > > depends on this clock also don't work (HDMI CEC for example).
> > > > 
> > > > Make clocks property optional. If it is present, select external
> > > > oscillator. If not, stay on internal.
> > > > 
> > > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > > ---
> > > > 
> > > >  drivers/rtc/rtc-sun6i.c | 14 ++++++--------
> > > >  1 file changed, 6 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> > > > index 852f5f3b3592..538cf7e19034 100644
> > > > --- a/drivers/rtc/rtc-sun6i.c
> > > > +++ b/drivers/rtc/rtc-sun6i.c
> > > > @@ -250,19 +250,17 @@ static void __init sun6i_rtc_clk_init(struct
> > > > device_node *node,>
> > > > 
> > > >  		writel(reg, rtc->base + SUN6I_LOSC_CTRL);
> > > >  	
> > > >  	}
> > > > 
> > > > -	/* Switch to the external, more precise, oscillator */
> > > > -	reg |= SUN6I_LOSC_CTRL_EXT_OSC;
> > > > -	if (rtc->data->has_losc_en)
> > > > -		reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
> > > > +	/* Switch to the external, more precise, oscillator, if present 
*/
> > > > +	if (of_get_property(node, "clocks", NULL)) {
> > > > +		reg |= SUN6I_LOSC_CTRL_EXT_OSC;
> > > > +		if (rtc->data->has_losc_en)
> > > > +			reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
> > > > +	}
> > > > 
> > > >  	writel(reg, rtc->base + SUN6I_LOSC_CTRL);
> > > >  	
> > > >  	/* Yes, I know, this is ugly. */
> > > >  	sun6i_rtc = rtc;
> > > > 
> > > > -	/* Deal with old DTs */
> > > > -	if (!of_get_property(node, "clocks", NULL))
> > > > -		goto err;
> > > > -
> > > 
> > > Doesn't that prevent the parents to be properly set if there's an
> > > external crystal?
> > 
> > No, why?
> > 
> > Check these two clk_summary:
> > http://ix.io/2bHY Tanix TX6 (no external crystal)
> > http://ix.io/2bI2 OrangePi 3 (external crystal present)
> 
> I was concerned about the "other" parent. In the case where you don't
> have a clocks property (so the check that you are removing), the code
> then registers a clock with two parents: the one that we create (the
> internal oscillator) and the one coming from the clocks property.
> 
> clk_summary only shows the current parent, which is going to be right
> with your patch, but in the case where you have no clocks property,
> you still (attempts to) register two parents, the second one being
> non-functional.
> 
> Further looking at it, we might be good because we allocate an array
> of two clocks, but only register of_clk_get_parent_count(node) + 1
> clocks, so 1 if clocks is missing.

Yes, my patch rely on "of_clk_get_parent_count(node) + 1". If there is no 
property, it will return 1 thus only first parent (internal RC oscilator) will 
be registered.

Anyway, following line:
parents[1] = of_clk_get_parent_name(node, 0);
should evaluate to null. I didn't research further what clk framework does 
with null parent because number of parents will be set to 1 and this null 
value will be ignored anyway.

> 
> Still, I think this should be more obvious, through a comment or
> shuffling a bit the parent registration maybe?

I think code is in correct order, just maybe a bit more explanation in form of 
comment(s) to make it more obvious how it works for either case.

Best regards,
Jernej



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 1/4] drm/connector: Add data polarity flags
From: Maxime Ripard @ 2020-02-20 18:00 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Chen-Yu Tsai, dri-devel, Maarten Lankhorst, Sean Paul,
	Daniel Vetter, David Airlie, devicetree, Mark Rutland,
	Rob Herring, Frank Rowand, Thierry Reding, linux-arm-kernel
In-Reply-To: <20200214161359.GB18287@ravnborg.org>

[-- Attachment #1: Type: text/plain, Size: 1486 bytes --]

On Fri, Feb 14, 2020 at 05:13:59PM +0100, Sam Ravnborg wrote:
> Hi Maxime.
>
> On Fri, Feb 14, 2020 at 01:24:38PM +0100, Maxime Ripard wrote:
> > Some LVDS encoders can change the polarity of the data signals being
> > sent. Add a DRM bus flag to reflect this.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  include/drm/drm_connector.h | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> > index 221910948b37..9a08fe6ab7c2 100644
> > --- a/include/drm/drm_connector.h
> > +++ b/include/drm/drm_connector.h
> > @@ -330,6 +330,8 @@ enum drm_panel_orientation {
> >   *					edge of the pixel clock
> >   * @DRM_BUS_FLAG_SHARP_SIGNALS:		Set if the Sharp-specific signals
> >   *					(SPL, CLS, PS, REV) must be used
> > + * @DRM_BUS_FLAG_DATA_LOW:		The Data signals are active low
> > + * @DRM_BUS_FLAG_DATA_HIGH:		The Data signals are active high
> Reading the description of these falgs always confuses me.
> In this case if neither bit 9 nor bit 10 is set then the data signals
> are netiher active low nor active high.
> So what can I then expect?
>
> We have the same logic loophole for DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE
> and DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE.
> So it is not new, but can we do better here?

Honestly, I don't really get it either. I *think* this is to handle
the sampling / output inversion properly which wouldn't be possible if
this was only a bit set or not.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* [Intel-gfx] ✗ Fi.CI.IGT: failure for series starting with [CI,01/10] drm/i915/debugfs: Pass guc_log struct to i915_guc_log_info
From: Patchwork @ 2020-02-20 18:00 UTC (permalink / raw)
  To: Daniele Ceraolo Spurio; +Cc: intel-gfx
In-Reply-To: <20200218223327.11058-1-daniele.ceraolospurio@intel.com>

== Series Details ==

Series: series starting with [CI,01/10] drm/i915/debugfs: Pass guc_log struct to i915_guc_log_info
URL   : https://patchwork.freedesktop.org/series/73610/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_7963_full -> Patchwork_16611_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_16611_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_16611_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_16611_full:

### IGT changes ###

#### Possible regressions ####

  * igt@gem_exec_balancer@bonded-slice:
    - shard-tglb:         [PASS][1] -> [FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-tglb5/igt@gem_exec_balancer@bonded-slice.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-tglb3/igt@gem_exec_balancer@bonded-slice.html

  
New tests
---------

  New tests have been introduced between CI_DRM_7963_full and Patchwork_16611_full:

### New IGT tests (58) ###

  * igt@i915_pm_backlight@bad-brightness:
    - Statuses : 3 pass(s) 4 skip(s)
    - Exec time: [0.0, 0.01] s

  * igt@i915_pm_backlight@basic-brightness:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 0.23] s

  * igt@i915_pm_backlight@fade:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 2.59] s

  * igt@i915_pm_backlight@fade_with_dpms:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 4.92] s

  * igt@i915_pm_backlight@fade_with_suspend:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 5.02] s

  * igt@i915_pm_lpsp@edp-native:
    - Statuses : 8 skip(s)
    - Exec time: [0.0, 0.04] s

  * igt@i915_pm_lpsp@edp-panel-fitter:
    - Statuses : 8 skip(s)
    - Exec time: [0.0, 0.05] s

  * igt@i915_pm_lpsp@non-edp:
    - Statuses : 1 pass(s) 7 skip(s)
    - Exec time: [0.0, 0.11] s

  * igt@i915_pm_lpsp@screens-disabled:
    - Statuses : 1 pass(s) 7 skip(s)
    - Exec time: [0.0, 0.04] s

  * igt@i915_pm_rc6_residency@media-rc6-accuracy:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@i915_pm_rc6_residency@rc6-accuracy:
    - Statuses : 8 pass(s)
    - Exec time: [3.00] s

  * igt@i915_pm_rpm@basic-pci-d3-state:
    - Statuses : 7 pass(s)
    - Exec time: [0.17, 4.97] s

  * igt@i915_pm_rpm@basic-rte:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [1.33, 11.39] s

  * igt@i915_pm_rpm@cursor:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 41.33] s

  * igt@i915_pm_rpm@cursor-dpms:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 40.58] s

  * igt@i915_pm_rpm@debugfs-forcewake-user:
    - Statuses : 7 pass(s)
    - Exec time: [10.31, 14.12] s

  * igt@i915_pm_rpm@debugfs-read:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 80.91] s

  * igt@i915_pm_rpm@dpms-lpsp:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 0.82] s

  * igt@i915_pm_rpm@dpms-mode-unset-lpsp:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 13.42] s

  * igt@i915_pm_rpm@dpms-mode-unset-non-lpsp:
    - Statuses : 4 pass(s) 4 skip(s)
    - Exec time: [0.0, 3.93] s

  * igt@i915_pm_rpm@dpms-non-lpsp:
    - Statuses : 4 pass(s) 3 skip(s)
    - Exec time: [0.0, 0.16] s

  * igt@i915_pm_rpm@drm-resources-equal:
    - Statuses : 6 pass(s) 1 skip(s)
    - Exec time: [0.0, 11.08] s

  * igt@i915_pm_rpm@fences:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 17.06] s

  * igt@i915_pm_rpm@fences-dpms:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 12.76] s

  * igt@i915_pm_rpm@gem-evict-pwrite:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 3.93] s

  * igt@i915_pm_rpm@gem-execbuf:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 14.10] s

  * igt@i915_pm_rpm@gem-execbuf-stress:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 42.76] s

  * igt@i915_pm_rpm@gem-execbuf-stress-pc8:
    - Statuses : 8 skip(s)
    - Exec time: [0.0, 0.01] s

  * igt@i915_pm_rpm@gem-idle:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 9.21] s

  * igt@i915_pm_rpm@gem-pread:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 6.37] s

  * igt@i915_pm_rpm@i2c:
    - Statuses : 6 pass(s)
    - Exec time: [1.39, 11.37] s

  * igt@i915_pm_rpm@legacy-planes:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 169.75] s

  * igt@i915_pm_rpm@legacy-planes-dpms:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 150.38] s

  * igt@i915_pm_rpm@modeset-lpsp:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 4.97] s

  * igt@i915_pm_rpm@modeset-lpsp-stress:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 55.05] s

  * igt@i915_pm_rpm@modeset-lpsp-stress-no-wait:
    - Statuses : 3 pass(s) 5 skip(s)
    - Exec time: [0.0, 17.88] s

  * igt@i915_pm_rpm@modeset-non-lpsp:
    - Statuses : 4 pass(s) 4 skip(s)
    - Exec time: [0.0, 4.12] s

  * igt@i915_pm_rpm@modeset-non-lpsp-stress:
    - Statuses : 4 pass(s) 4 skip(s)
    - Exec time: [0.0, 8.96] s

  * igt@i915_pm_rpm@modeset-non-lpsp-stress-no-wait:
    - Statuses : 4 pass(s) 4 skip(s)
    - Exec time: [0.0, 8.36] s

  * igt@i915_pm_rpm@modeset-pc8-residency-stress:
    - Statuses : 8 skip(s)
    - Exec time: [0.0] s

  * igt@i915_pm_rpm@modeset-stress-extra-wait:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 72.03] s

  * igt@i915_pm_rpm@pc8-residency:
    - Statuses : 8 skip(s)
    - Exec time: [0.0] s

  * igt@i915_pm_rpm@pm-caching:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 19.95] s

  * igt@i915_pm_rpm@pm-tiling:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 15.08] s

  * igt@i915_pm_rpm@reg-read-ioctl:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 8.00] s

  * igt@i915_pm_rpm@sysfs-read:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 4.16] s

  * igt@i915_pm_rpm@system-suspend:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 9.12] s

  * igt@i915_pm_rpm@system-suspend-devices:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 13.48] s

  * igt@i915_pm_rpm@system-suspend-execbuf:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 86.14] s

  * igt@i915_pm_rpm@system-suspend-modeset:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 14.80] s

  * igt@i915_pm_rpm@universal-planes:
    - Statuses : 7 pass(s)
    - Exec time: [2.95, 226.00] s

  * igt@i915_pm_rpm@universal-planes-dpms:
    - Statuses : 7 pass(s) 1 skip(s)
    - Exec time: [0.0, 195.58] s

  * igt@i915_pm_rps@basic-api:
    - Statuses : 8 pass(s)
    - Exec time: [0.00, 0.03] s

  * igt@i915_pm_rps@min-max-config-idle:
    - Statuses : 8 pass(s)
    - Exec time: [0.11, 0.88] s

  * igt@i915_pm_rps@min-max-config-loaded:
    - Statuses : 1 fail(s) 7 pass(s)
    - Exec time: [0.31, 3.02] s

  * igt@i915_pm_rps@reset:
    - Statuses : 1 fail(s) 7 pass(s)
    - Exec time: [3.52, 3.69] s

  * igt@i915_pm_rps@waitboost:
    - Statuses : 1 fail(s) 7 pass(s)
    - Exec time: [2.52, 2.64] s

  * igt@i915_pm_sseu@full-enable:
    - Statuses : 4 pass(s) 4 skip(s)
    - Exec time: [0.0, 0.01] s

  

Known issues
------------

  Here are the changes found in Patchwork_16611_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_isolation@vcs0-s3:
    - shard-skl:          [PASS][3] -> [INCOMPLETE][4] ([i915#69])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl8/igt@gem_ctx_isolation@vcs0-s3.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl1/igt@gem_ctx_isolation@vcs0-s3.html

  * igt@gem_ctx_shared@exec-single-timeline-bsd:
    - shard-iclb:         [PASS][5] -> [SKIP][6] ([fdo#110841])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb5/igt@gem_ctx_shared@exec-single-timeline-bsd.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb1/igt@gem_ctx_shared@exec-single-timeline-bsd.html

  * igt@gem_exec_balancer@hang:
    - shard-tglb:         [PASS][7] -> [FAIL][8] ([i915#1127])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-tglb2/igt@gem_exec_balancer@hang.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-tglb6/igt@gem_exec_balancer@hang.html

  * igt@gem_exec_parallel@vcs1-fds:
    - shard-iclb:         [PASS][9] -> [SKIP][10] ([fdo#112080]) +9 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb1/igt@gem_exec_parallel@vcs1-fds.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb3/igt@gem_exec_parallel@vcs1-fds.html

  * igt@gem_exec_schedule@reorder-wide-bsd:
    - shard-iclb:         [PASS][11] -> [SKIP][12] ([fdo#112146]) +3 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb3/igt@gem_exec_schedule@reorder-wide-bsd.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb2/igt@gem_exec_schedule@reorder-wide-bsd.html

  * igt@gem_partial_pwrite_pread@writes-after-reads-uncached:
    - shard-hsw:          [PASS][13] -> [FAIL][14] ([i915#694]) +1 similar issue
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-hsw2/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-hsw4/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html

  * igt@i915_selftest@live_gt_lrc:
    - shard-tglb:         [PASS][15] -> [INCOMPLETE][16] ([i915#1233])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-tglb8/igt@i915_selftest@live_gt_lrc.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-tglb8/igt@i915_selftest@live_gt_lrc.html

  * igt@i915_selftest@live_gtt:
    - shard-skl:          [PASS][17] -> [TIMEOUT][18] ([fdo#111732] / [fdo#112271])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl7/igt@i915_selftest@live_gtt.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl7/igt@i915_selftest@live_gtt.html

  * igt@kms_cursor_crc@pipe-c-cursor-256x256-sliding:
    - shard-skl:          [PASS][19] -> [FAIL][20] ([i915#54])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl7/igt@kms_cursor_crc@pipe-c-cursor-256x256-sliding.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl3/igt@kms_cursor_crc@pipe-c-cursor-256x256-sliding.html

  * igt@kms_flip@flip-vs-absolute-wf_vblank:
    - shard-tglb:         [PASS][21] -> [FAIL][22] ([i915#488])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-tglb5/igt@kms_flip@flip-vs-absolute-wf_vblank.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-tglb5/igt@kms_flip@flip-vs-absolute-wf_vblank.html

  * igt@kms_flip@flip-vs-suspend:
    - shard-apl:          [PASS][23] -> [DMESG-WARN][24] ([i915#180])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-apl4/igt@kms_flip@flip-vs-suspend.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-apl6/igt@kms_flip@flip-vs-suspend.html

  * igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-pwrite:
    - shard-glk:          [PASS][25] -> [FAIL][26] ([i915#49])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-glk9/igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-pwrite.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-glk3/igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-cpu:
    - shard-skl:          [PASS][27] -> [FAIL][28] ([i915#49])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl1/igt@kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-cpu.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl10/igt@kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-cpu.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min:
    - shard-skl:          [PASS][29] -> [FAIL][30] ([fdo#108145])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl1/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl10/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html

  * igt@kms_plane_lowres@pipe-a-tiling-y:
    - shard-glk:          [PASS][31] -> [FAIL][32] ([i915#899])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-glk9/igt@kms_plane_lowres@pipe-a-tiling-y.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-glk3/igt@kms_plane_lowres@pipe-a-tiling-y.html

  * igt@kms_psr@psr2_cursor_mmap_cpu:
    - shard-iclb:         [PASS][33] -> [SKIP][34] ([fdo#109441]) +2 similar issues
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb2/igt@kms_psr@psr2_cursor_mmap_cpu.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb4/igt@kms_psr@psr2_cursor_mmap_cpu.html

  * igt@prime_vgem@wait-bsd2:
    - shard-iclb:         [PASS][35] -> [SKIP][36] ([fdo#109276]) +15 similar issues
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb1/igt@prime_vgem@wait-bsd2.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb7/igt@prime_vgem@wait-bsd2.html

  
#### Possible fixes ####

  * {igt@gem_ctx_persistence@close-replace-race}:
    - shard-iclb:         [FAIL][37] ([i915#1241]) -> [PASS][38]
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb1/igt@gem_ctx_persistence@close-replace-race.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb7/igt@gem_ctx_persistence@close-replace-race.html

  * {igt@gem_ctx_persistence@legacy-engines-mixed-process@vebox}:
    - shard-skl:          [FAIL][39] ([i915#679]) -> [PASS][40]
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl8/igt@gem_ctx_persistence@legacy-engines-mixed-process@vebox.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl7/igt@gem_ctx_persistence@legacy-engines-mixed-process@vebox.html

  * {igt@gem_exec_schedule@implicit-write-read-bsd1}:
    - shard-iclb:         [SKIP][41] ([fdo#109276] / [i915#677]) -> [PASS][42]
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb7/igt@gem_exec_schedule@implicit-write-read-bsd1.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb4/igt@gem_exec_schedule@implicit-write-read-bsd1.html

  * igt@gem_exec_schedule@pi-distinct-iova-bsd:
    - shard-iclb:         [SKIP][43] ([i915#677]) -> [PASS][44] +1 similar issue
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb1/igt@gem_exec_schedule@pi-distinct-iova-bsd.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb7/igt@gem_exec_schedule@pi-distinct-iova-bsd.html

  * igt@gem_exec_schedule@preemptive-hang-bsd:
    - shard-iclb:         [SKIP][45] ([fdo#112146]) -> [PASS][46] +3 similar issues
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb1/igt@gem_exec_schedule@preemptive-hang-bsd.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb7/igt@gem_exec_schedule@preemptive-hang-bsd.html

  * igt@gem_exec_schedule@promotion-bsd1:
    - shard-iclb:         [SKIP][47] ([fdo#109276]) -> [PASS][48] +12 similar issues
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb7/igt@gem_exec_schedule@promotion-bsd1.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb4/igt@gem_exec_schedule@promotion-bsd1.html

  * igt@gem_ppgtt@flink-and-close-vma-leak:
    - shard-apl:          [FAIL][49] ([i915#644]) -> [PASS][50]
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-apl1/igt@gem_ppgtt@flink-and-close-vma-leak.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-apl1/igt@gem_ppgtt@flink-and-close-vma-leak.html

  * igt@kms_cursor_crc@pipe-a-cursor-size-change:
    - shard-snb:          [SKIP][51] ([fdo#109271]) -> [PASS][52] +1 similar issue
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-snb4/igt@kms_cursor_crc@pipe-a-cursor-size-change.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-snb5/igt@kms_cursor_crc@pipe-a-cursor-size-change.html

  * igt@kms_cursor_legacy@2x-long-cursor-vs-flip-legacy:
    - shard-hsw:          [FAIL][53] ([i915#96]) -> [PASS][54]
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-hsw8/igt@kms_cursor_legacy@2x-long-cursor-vs-flip-legacy.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-hsw7/igt@kms_cursor_legacy@2x-long-cursor-vs-flip-legacy.html

  * igt@kms_fbcon_fbt@fbc-suspend:
    - shard-kbl:          [DMESG-WARN][55] ([i915#180]) -> [PASS][56]
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-kbl1/igt@kms_fbcon_fbt@fbc-suspend.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-kbl2/igt@kms_fbcon_fbt@fbc-suspend.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible:
    - shard-skl:          [FAIL][57] ([i915#79]) -> [PASS][58]
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl5/igt@kms_flip@flip-vs-expired-vblank-interruptible.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl6/igt@kms_flip@flip-vs-expired-vblank-interruptible.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-hsw:          [INCOMPLETE][59] ([i915#61]) -> [PASS][60]
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-hsw2/igt@kms_flip@flip-vs-suspend-interruptible.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-hsw1/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_frontbuffer_tracking@psr-1p-rte:
    - shard-tglb:         [SKIP][61] ([i915#668]) -> [PASS][62]
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-tglb5/igt@kms_frontbuffer_tracking@psr-1p-rte.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-tglb5/igt@kms_frontbuffer_tracking@psr-1p-rte.html

  * igt@kms_plane@plane-panning-bottom-right-suspend-pipe-b-planes:
    - shard-apl:          [DMESG-WARN][63] ([i915#180]) -> [PASS][64] +3 similar issues
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-apl1/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-b-planes.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-apl4/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-b-planes.html

  * igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min:
    - shard-skl:          [FAIL][65] ([fdo#108145]) -> [PASS][66]
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl8/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl1/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html

  * igt@kms_psr@no_drrs:
    - shard-iclb:         [FAIL][67] ([i915#173]) -> [PASS][68]
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb1/igt@kms_psr@no_drrs.html
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb7/igt@kms_psr@no_drrs.html

  * igt@kms_psr@psr2_sprite_mmap_gtt:
    - shard-iclb:         [SKIP][69] ([fdo#109441]) -> [PASS][70] +3 similar issues
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb1/igt@kms_psr@psr2_sprite_mmap_gtt.html
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb2/igt@kms_psr@psr2_sprite_mmap_gtt.html

  * igt@kms_vblank@pipe-a-ts-continuation-suspend:
    - shard-skl:          [INCOMPLETE][71] ([i915#69]) -> [PASS][72]
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-skl3/igt@kms_vblank@pipe-a-ts-continuation-suspend.html
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-skl10/igt@kms_vblank@pipe-a-ts-continuation-suspend.html

  * igt@kms_vblank@pipe-c-ts-continuation-dpms-suspend:
    - shard-kbl:          [INCOMPLETE][73] ([fdo#103665]) -> [PASS][74]
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-kbl6/igt@kms_vblank@pipe-c-ts-continuation-dpms-suspend.html
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-kbl7/igt@kms_vblank@pipe-c-ts-continuation-dpms-suspend.html

  * igt@perf@short-reads:
    - shard-kbl:          [TIMEOUT][75] ([fdo#112271] / [i915#51]) -> [PASS][76]
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-kbl6/igt@perf@short-reads.html
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-kbl4/igt@perf@short-reads.html

  * igt@perf_pmu@busy-no-semaphores-vcs1:
    - shard-iclb:         [SKIP][77] ([fdo#112080]) -> [PASS][78] +9 similar issues
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb7/igt@perf_pmu@busy-no-semaphores-vcs1.html
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb2/igt@perf_pmu@busy-no-semaphores-vcs1.html

  * igt@prime_mmap_coherency@ioctl-errors:
    - shard-hsw:          [FAIL][79] ([i915#831]) -> [PASS][80]
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-hsw2/igt@prime_mmap_coherency@ioctl-errors.html
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-hsw1/igt@prime_mmap_coherency@ioctl-errors.html

  
#### Warnings ####

  * igt@gem_ctx_isolation@vcs1-nonpriv-switch:
    - shard-iclb:         [SKIP][81] ([fdo#112080]) -> [FAIL][82] ([IGT#28])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-iclb7/igt@gem_ctx_isolation@vcs1-nonpriv-switch.html
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-iclb4/igt@gem_ctx_isolation@vcs1-nonpriv-switch.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-tglb:         [FAIL][83] ([i915#454]) -> [SKIP][84] ([i915#468]) +1 similar issue
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7963/shard-tglb6/igt@i915_pm_dc@dc6-psr.html
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/shard-tglb2/igt@i915_pm_dc@dc6-psr.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [IGT#28]: https://gitlab.freedesktop.org/drm/igt-gpu-tools/issues/28
  [fdo#103665]: https://bugs.freedesktop.org/show_bug.cgi?id=103665
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109276]: https://bugs.freedesktop.org/show_bug.cgi?id=109276
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#110841]: https://bugs.freedesktop.org/show_bug.cgi?id=110841
  [fdo#111732]: https://bugs.freedesktop.org/show_bug.cgi?id=111732
  [fdo#112080]: https://bugs.freedesktop.org/show_bug.cgi?id=112080
  [fdo#112146]: https://bugs.freedesktop.org/show_bug.cgi?id=112146
  [fdo#112271]: https://bugs.freedesktop.org/show_bug.cgi?id=112271
  [i915#1127]: https://gitlab.freedesktop.org/drm/intel/issues/1127
  [i915#1233]: https://gitlab.freedesktop.org/drm/intel/issues/1233
  [i915#1241]: https://gitlab.freedesktop.org/drm/intel/issues/1241
  [i915#173]: https://gitlab.freedesktop.org/drm/intel/issues/173
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#454]: https://gitlab.freedesktop.org/drm/intel/issues/454
  [i915#468]: https://gitlab.freedesktop.org/drm/intel/issues/468
  [i915#488]: https://gitlab.freedesktop.org/drm/intel/issues/488
  [i915#49]: https://gitlab.freedesktop.org/drm/intel/issues/49
  [i915#51]: https://gitlab.freedesktop.org/drm/intel/issues/51
  [i915#54]: https://gitlab.freedesktop.org/drm/intel/issues/54
  [i915#61]: https://gitlab.freedesktop.org/drm/intel/issues/61
  [i915#644]: https://gitlab.freedesktop.org/drm/intel/issues/644
  [i915#668]: https://gitlab.freedesktop.org/drm/intel/issues/668
  [i915#677]: https://gitlab.freedesktop.org/drm/intel/issues/677
  [i915#679]: https://gitlab.freedesktop.org/drm/intel/issues/679
  [i915#69]: https://gitlab.freedesktop.org/drm/intel/issues/69
  [i915#694]: https://gitlab.freedesktop.org/drm/intel/issues/694
  [i915#79]: https://gitlab.freedesktop.org/drm/intel/issues/79
  [i915#831]: https://gitlab.freedesktop.org/drm/intel/issues/831
  [i915#899]: https://gitlab.freedesktop.org/drm/intel/issues/899
  [i915#96]: https://gitlab.freedesktop.org/drm/intel/issues/96


Participating hosts (10 -> 10)
------------------------------

  No changes in participating hosts


Build changes
-------------

  * CI: CI-20190529 -> None
  * Linux: CI_DRM_7963 -> Patchwork_16611

  CI-20190529: 20190529
  CI_DRM_7963: e0d737598eb749378a5dc4ed3dfafc6f79d512cb @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5448: 116020b1f83c1b3994c76882df7f77b6731d78ba @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_16611: 50bb392a051d3d642110516f74f2a22ab49e90b4 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_16611/index.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: [PATCH 2/2] xfs: ratelimit xfs_discard_page messages
From: Brian Foster @ 2020-02-20 17:59 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs
In-Reply-To: <20200220153921.383899-3-hch@lst.de>

On Thu, Feb 20, 2020 at 07:39:21AM -0800, Christoph Hellwig wrote:
> Use printk_ratelimit() to limit the amount of messages printed from
> xfs_discard_page.  Without that a failing device causes a large
> number of errors that doesn't really help debugging the underling
> issue.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_aops.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index 58e937be24ce..9d9cebf18726 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -539,7 +539,7 @@ xfs_discard_page(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		goto out_invalidate;
>  
> -	xfs_alert(mp,
> +	xfs_alert_ratelimited(mp,
>  		"page discard on page "PTR_FMT", inode 0x%llx, offset %llu.",
>  			page, ip->i_ino, offset);
>  
> -- 
> 2.24.1
> 


^ permalink raw reply

* Re: [PATCH 1/2] rtc: sun6i: Make external 32k oscillator optional
From: Jernej Škrabec @ 2020-02-20 17:59 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: wens, robh+dt, mark.rutland, a.zummo, alexandre.belloni,
	linux-arm-kernel, devicetree, linux-kernel, linux-rtc
In-Reply-To: <20200220174749.ih3pcj3oxiwvuurz@gilmour.lan>

Dne četrtek, 20. februar 2020 ob 18:47:49 CET je Maxime Ripard napisal(a):
> On Fri, Feb 14, 2020 at 05:42:13PM +0100, Jernej Škrabec wrote:
> > Hi Maxime,
> > 
> > Dne petek, 14. februar 2020 ob 09:14:43 CET je Maxime Ripard napisal(a):
> > > Hi Jernej,
> > > 
> > > Thanks for taking care of this
> > > 
> > > On Thu, Feb 13, 2020 at 10:14:26PM +0100, Jernej Skrabec wrote:
> > > > Some boards, like OrangePi PC2 (H5), OrangePi Plus 2E (H3) and Tanix
> > > > TX6
> > > > (H6) don't have external 32kHz oscillator. Till H6, it didn't really
> > > > matter if external oscillator was enabled because HW detected error
> > > > and
> > > > fall back to internal one. H6 has same functionality but it's the
> > > > first
> > > > SoC which have "auto switch bypass" bit documented and always enabled
> > > > in
> > > > driver. This prevents RTC to work correctly if external crystal is not
> > > > present on board. There are other side effects - all peripherals which
> > > > depends on this clock also don't work (HDMI CEC for example).
> > > > 
> > > > Make clocks property optional. If it is present, select external
> > > > oscillator. If not, stay on internal.
> > > > 
> > > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > > ---
> > > > 
> > > >  drivers/rtc/rtc-sun6i.c | 14 ++++++--------
> > > >  1 file changed, 6 insertions(+), 8 deletions(-)
> > > > 
> > > > diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> > > > index 852f5f3b3592..538cf7e19034 100644
> > > > --- a/drivers/rtc/rtc-sun6i.c
> > > > +++ b/drivers/rtc/rtc-sun6i.c
> > > > @@ -250,19 +250,17 @@ static void __init sun6i_rtc_clk_init(struct
> > > > device_node *node,>
> > > > 
> > > >  		writel(reg, rtc->base + SUN6I_LOSC_CTRL);
> > > >  	
> > > >  	}
> > > > 
> > > > -	/* Switch to the external, more precise, oscillator */
> > > > -	reg |= SUN6I_LOSC_CTRL_EXT_OSC;
> > > > -	if (rtc->data->has_losc_en)
> > > > -		reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
> > > > +	/* Switch to the external, more precise, oscillator, if present 
*/
> > > > +	if (of_get_property(node, "clocks", NULL)) {
> > > > +		reg |= SUN6I_LOSC_CTRL_EXT_OSC;
> > > > +		if (rtc->data->has_losc_en)
> > > > +			reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
> > > > +	}
> > > > 
> > > >  	writel(reg, rtc->base + SUN6I_LOSC_CTRL);
> > > >  	
> > > >  	/* Yes, I know, this is ugly. */
> > > >  	sun6i_rtc = rtc;
> > > > 
> > > > -	/* Deal with old DTs */
> > > > -	if (!of_get_property(node, "clocks", NULL))
> > > > -		goto err;
> > > > -
> > > 
> > > Doesn't that prevent the parents to be properly set if there's an
> > > external crystal?
> > 
> > No, why?
> > 
> > Check these two clk_summary:
> > http://ix.io/2bHY Tanix TX6 (no external crystal)
> > http://ix.io/2bI2 OrangePi 3 (external crystal present)
> 
> I was concerned about the "other" parent. In the case where you don't
> have a clocks property (so the check that you are removing), the code
> then registers a clock with two parents: the one that we create (the
> internal oscillator) and the one coming from the clocks property.
> 
> clk_summary only shows the current parent, which is going to be right
> with your patch, but in the case where you have no clocks property,
> you still (attempts to) register two parents, the second one being
> non-functional.
> 
> Further looking at it, we might be good because we allocate an array
> of two clocks, but only register of_clk_get_parent_count(node) + 1
> clocks, so 1 if clocks is missing.

Yes, my patch rely on "of_clk_get_parent_count(node) + 1". If there is no 
property, it will return 1 thus only first parent (internal RC oscilator) will 
be registered.

Anyway, following line:
parents[1] = of_clk_get_parent_name(node, 0);
should evaluate to null. I didn't research further what clk framework does 
with null parent because number of parents will be set to 1 and this null 
value will be ignored anyway.

> 
> Still, I think this should be more obvious, through a comment or
> shuffling a bit the parent registration maybe?

I think code is in correct order, just maybe a bit more explanation in form of 
comment(s) to make it more obvious how it works for either case.

Best regards,
Jernej



^ permalink raw reply

* Re: [PATCH 1/2] xfs: ratelimit xfs_buf_ioerror_alert messages
From: Brian Foster @ 2020-02-20 17:59 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs
In-Reply-To: <20200220153921.383899-2-hch@lst.de>

On Thu, Feb 20, 2020 at 07:39:20AM -0800, Christoph Hellwig wrote:
> Use printk_ratelimit() to limit the amount of messages printed from
> xfs_buf_ioerror_alert.  Without that a failing device causes a large
> number of errors that doesn't really help debugging the underling
> issue.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_buf.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
> index 217e4f82a44a..0ceaa172545b 100644
> --- a/fs/xfs/xfs_buf.c
> +++ b/fs/xfs/xfs_buf.c
> @@ -1238,7 +1238,7 @@ xfs_buf_ioerror_alert(
>  	struct xfs_buf		*bp,
>  	xfs_failaddr_t		func)
>  {
> -	xfs_alert(bp->b_mount,
> +	xfs_alert_ratelimited(bp->b_mount,
>  "metadata I/O error in \"%pS\" at daddr 0x%llx len %d error %d",
>  			func, (uint64_t)XFS_BUF_ADDR(bp), bp->b_length,
>  			-bp->b_error);
> -- 
> 2.24.1
> 


^ permalink raw reply

* Re: [PATCH] tcg: gdbstub: Fix single-step issue on arm target
From: Peter Maydell @ 2020-02-20 17:58 UTC (permalink / raw)
  To: Changbin Du
  Cc: Philippe Mathieu-Daudé, Alex Bennée, QEMU Developers
In-Reply-To: <20200220155834.21905-1-changbin.du@gmail.com>

On Thu, 20 Feb 2020 at 15:59, Changbin Du <changbin.du@gmail.com> wrote:
>
> Recently when debugging an arm32 system on qemu, I found sometimes the
> single-step command (stepi) is not working. This can be reproduced by
> below steps:
>  1) start qemu-system-arm -s -S .. and wait for gdb connection.
>  2) start gdb and connect to qemu. In my case, gdb gets a wrong value
>     (0x60) for PC.
>  3) After connected, type 'stepi' and expect it will stop at next ins.
>
> But, it has never stopped. This because:
>  1) We doesn't report ‘vContSupported’ feature to gdb explicitly and gdb
>     think we do not support it. In this case, gdb use a software breakpoint
>     to emulate single-step.
>  2) Since gdb gets a wrong initial value of PC, then gdb inserts a
>     breakpoint to wrong place (PC+4).
>
> Since we do support ‘vContSupported’ query command, so let's tell gdb that
> we support it.
>
> Before this change, gdb send below 'Z0' packet to implement single-step:
> gdb_handle_packet: Z0,4,4
>
> After this change, gdb send "vCont;s.." which is expected:
> gdb_handle_packet: vCont?
> put_packet: vCont;c;C;s;S
> gdb_handle_packet: vCont;s:p1.1;c:p1.-1
>
> Signed-off-by: Changbin Du <changbin.du@gmail.com>

Certainly if we support vCont we should advertise it. But why
does the fallback path not work? That is, why does gdb get a
wrong PC value initially?

thanks
-- PMM


^ permalink raw reply

* Re: [PATCH v3 1/8] dt-bindings: remoteproc: Add Qualcomm PIL info binding
From: Mathieu Poirier @ 2020-02-20 17:59 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ohad Ben-Cohen, Rob Herring, Mark Rutland, Andy Gross,
	linux-arm-msm, linux-remoteproc, devicetree, linux-kernel,
	Sibi Sankar, Rishabh Bhatnagar
In-Reply-To: <20200211005059.1377279-2-bjorn.andersson@linaro.org>

On Mon, Feb 10, 2020 at 04:50:52PM -0800, Bjorn Andersson wrote:
> Add a devicetree binding for the Qualcomm periperal image loader

s/periperal/peripheral

> relocation info region found in the IMEM.

s/info/information

> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
> 
> Changes since v2:
> - Replaced offset with reg to describe the region of IMEM used for the entries
> 
>  .../bindings/remoteproc/qcom,pil-info.yaml    | 42 +++++++++++++++++++
>  1 file changed, 42 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml
> 
> diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml
> new file mode 100644
> index 000000000000..8386a4da6030
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml
> @@ -0,0 +1,42 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/remoteproc/qcom,pil-info.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm peripheral image loader relocation info binding
> +
> +maintainers:
> +  - Bjorn Andersson <bjorn.andersson@linaro.org>
> +
> +description:
> +  This document defines the binding for describing the Qualcomm peripheral
> +  image loader relocation memory region, in IMEM, which is used for post mortem
> +  debugging of remoteprocs.
> +
> +properties:
> +  compatible:
> +    const: qcom,pil-reloc-info
> +
> +  reg:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +
> +examples:
> +  - |
> +    imem@146bf000 {
> +      compatible = "syscon", "simple-mfd";
> +      reg = <0 0x146bf000 0 0x1000>;
> +
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +
> +      pil-reloc {
> +        compatible ="qcom,pil-reloc-info";

s/="/= "

> +        reg = <0x94c 200>;
> +      };
> +    };
> +...
> -- 
> 2.24.0
> 

^ permalink raw reply

* Re: [PATCH 5/8] xfs_db: check that metadata updates have been committed
From: Brian Foster @ 2020-02-20 17:58 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs
In-Reply-To: <20200220165840.GX9506@magnolia>

On Thu, Feb 20, 2020 at 08:58:40AM -0800, Darrick J. Wong wrote:
> On Thu, Feb 20, 2020 at 09:06:23AM -0500, Brian Foster wrote:
> > On Wed, Feb 19, 2020 at 05:42:13PM -0800, Darrick J. Wong wrote:
> > > From: Darrick J. Wong <darrick.wong@oracle.com>
> > > 
> > > Add a new function that will ensure that everything we scribbled on has
> > > landed on stable media, and report the results.
> > > 
> > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > ---
> > >  db/init.c |   14 ++++++++++++++
> > >  1 file changed, 14 insertions(+)
> > > 
> > > 
> > > diff --git a/db/init.c b/db/init.c
> > > index 0ac37368..e92de232 100644
> > > --- a/db/init.c
> > > +++ b/db/init.c
> > > @@ -184,6 +184,7 @@ main(
> > >  	char	*input;
> > >  	char	**v;
> > >  	int	start_iocur_sp;
> > > +	int	d, l, r;
> > >  
> > >  	init(argc, argv);
> > >  	start_iocur_sp = iocur_sp;
> > > @@ -216,6 +217,19 @@ main(
> > >  	 */
> > >  	while (iocur_sp > start_iocur_sp)
> > >  		pop_cur();
> > > +
> > > +	libxfs_flush_devices(mp, &d, &l, &r);
> > > +	if (d)
> > > +		fprintf(stderr, _("%s: cannot flush data device (%d).\n"),
> > > +				progname, d);
> > > +	if (l)
> > > +		fprintf(stderr, _("%s: cannot flush log device (%d).\n"),
> > > +				progname, l);
> > > +	if (r)
> > > +		fprintf(stderr, _("%s: cannot flush realtime device (%d).\n"),
> > > +				progname, r);
> > > +
> > > +
> > 
> > Seems like we could reduce some boilerplate by passing progname into
> > libxfs_flush_devices() and letting it dump out of the error messages,
> > unless there's some future code that cares about individual device error
> > state.
> 
> Such a program could call libxfs_flush_devices directly, as we do here.
> 

Right.. but does anything actually care about that level of granularity
right now beyond having a nicer error message?

> Also, progname is defined in libxfs so we don't even need to pass it as
> an argument.
> 

Ok.

> I had originally thought that we should try not to add fprintf calls to
> libxfs because libraries aren't really supposed to be doing things like
> that, but perhaps you're right that all of this should be melded into
> something else.
> 

Yeah, fair point, though I guess it depends on the particular library. 

> > That said, it also seems the semantics of libxfs_flush_devices() are a
> > bit different from convention. Just below we invoke
> > libxfs_device_close() for each device (rather than for all three), and
> > device_close() also happens to call fsync() and platform_flush_device()
> > itself...
> 
> Yeah, the division of responsibilities is a little hazy here -- I would
> think that unmounting a filesystem should flush all the memory caches
> and then the disk cache, but OTOH it's the utility that opens the
> devices and should therefore flush and close them.
> 
> I dunno.  My current thinking is that libxfs_umount should call
> libxfs_flush_devices() and print error messages as necessary, and return
> error codes as appropriate.  xfs_repair can then check the umount return
> value and translate that into exit(1) as required.  The device_close
> functions will fsync a second time, but that shouldn't be a big deal
> because we haven't dirtied anything in the meantime.
> 
> Thoughts?
> 

I was thinking of having a per-device libxfs_device_flush() along the
lines of libxfs_device_close() and separating out that functionality,
but one could argue we're also a bit inconsistent between libxfs_init()
opening the devices and having to close them individually. I think
having libxfs_umount() do a proper purge -> flush and returning any
errors instead is a fair tradeoff for simplicity. Removing the
flush_devices() API also eliminates risk of somebody incorrectly
attempting the flush after the umount frees the buftarg structures
(without reinitializing pointers :P).

Brian

> --D
> 
> > Brian
> > 
> > >  	libxfs_umount(mp);
> > >  	if (x.ddev)
> > >  		libxfs_device_close(x.ddev);
> > > 
> > 
> 


^ permalink raw reply

* Major changes; please cherry-pick patches since 2020-02-05 and re-submit
From: Jody Bruchon @ 2020-02-20 17:59 UTC (permalink / raw)
  To: ELKS

Greetings, friends. This message is to clear up any confusion regarding 
what happened to the ELKS repository and where we go from here.

The elks-org organization on Github has been deleted. The project repo 
has been restored to my original location:

https://github.com/jbruchon/elks

I have force-pushed my version of the repo from February 5, 2020. Please 
cherry-pick and re-submit (as a pull request on Github) all of your 
patches since then for individual consideration, along with the 
rationale for acceptance of the patch. An issue has been opened on the 
project with this same request. I will be reviewing and approving all 
pull requests myself for the foreseeable future.

I apologize for the inconvenience that I know this will cause. This 
change in project management is not up for discussion and I will not 
entertain any attempts to discuss it. Those who disagree with it are 
free to fork the project and go their own way. All contributions are 
very welcome, but you will all have to check your egos and attitudes at 
the door.

Thanks to everyone for your past, present, and hopefully future support 
of this project.

Administrative notes: I'm re-subscribed to this mailing list, so please 
do not CC me in replies to the list. Discussion on the project issue 
tracker is the preferred method of collaboration. That is all.

Best regards,
Jody Bruchon

^ permalink raw reply

* Re: [PATCH 4/8] libxfs: enable tools to check that metadata updates have been committed
From: Brian Foster @ 2020-02-20 17:58 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs
In-Reply-To: <20200220164638.GW9506@magnolia>

On Thu, Feb 20, 2020 at 08:46:38AM -0800, Darrick J. Wong wrote:
> On Thu, Feb 20, 2020 at 09:06:12AM -0500, Brian Foster wrote:
> > On Wed, Feb 19, 2020 at 05:42:06PM -0800, Darrick J. Wong wrote:
> > > From: Darrick J. Wong <darrick.wong@oracle.com>
> > > 
> > > Add a new function that will ensure that everything we changed has
> > > landed on stable media, and report the results.  Subsequent commits will
> > > teach the individual programs to report when things go wrong.
> > > 
> > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > ---
> > >  include/xfs_mount.h |    3 +++
> > >  libxfs/init.c       |   43 +++++++++++++++++++++++++++++++++++++++++++
> > >  libxfs/libxfs_io.h  |    2 ++
> > >  libxfs/rdwr.c       |   27 +++++++++++++++++++++++++--
> > >  4 files changed, 73 insertions(+), 2 deletions(-)
> > > 
> > > 
> > > diff --git a/include/xfs_mount.h b/include/xfs_mount.h
> > > index 29b3cc1b..c80aaf69 100644
> > > --- a/include/xfs_mount.h
> > > +++ b/include/xfs_mount.h
> > > @@ -187,4 +187,7 @@ extern xfs_mount_t	*libxfs_mount (xfs_mount_t *, xfs_sb_t *,
> > >  extern void	libxfs_umount (xfs_mount_t *);
> > >  extern void	libxfs_rtmount_destroy (xfs_mount_t *);
> > >  
> > > +void libxfs_flush_devices(struct xfs_mount *mp, int *datadev, int *logdev,
> > > +		int *rtdev);
> > > +
> > >  #endif	/* __XFS_MOUNT_H__ */
> > > diff --git a/libxfs/init.c b/libxfs/init.c
> > > index a0d4b7f4..d1d3f4df 100644
> > > --- a/libxfs/init.c
> > > +++ b/libxfs/init.c
> > > @@ -569,6 +569,8 @@ libxfs_buftarg_alloc(
> > >  	}
> > >  	btp->bt_mount = mp;
> > >  	btp->dev = dev;
> > > +	btp->lost_writes = false;
> > > +
> > >  	return btp;
> > >  }
> > >  
> > > @@ -791,6 +793,47 @@ libxfs_rtmount_destroy(xfs_mount_t *mp)
> > >  	mp->m_rsumip = mp->m_rbmip = NULL;
> > >  }
> > >  
> > > +static inline int
> > > +libxfs_flush_buftarg(
> > > +	struct xfs_buftarg	*btp)
> > > +{
> > > +	if (btp->lost_writes)
> > > +		return -ENOTRECOVERABLE;
> > 
> > I'm curious why we'd want to skip the flush just because some writes
> > happened to fail..? I suppose the fs might be borked, but it seems a
> > little strange to at least not try the flush, particularly since we
> > might still flush any of the other two possible devices.
> 
> My thinking here was that if the write verifiers (or the pwrite() calls
> themselves) failed then there's no point in telling the disk to flush
> its write cache since we already know it's not in sync with the buffer
> cache.
> 

I suppose, but it seems there is some value in flushing what we did
write.. That's effectively historical behavior (since we ignored
errors), right?

> > > +
> > > +	return libxfs_blkdev_issue_flush(btp);
> > > +}
> > > +
> > > +/*
> > > + * Purge the buffer cache to write all dirty buffers to disk and free all
> > > + * incore buffers.  Buffers that cannot be written will cause the lost_writes
> > > + * flag to be set in the buftarg.  If there were no lost writes, flush the
> > > + * device to make sure the writes made it to stable storage.
> > > + *
> > > + * For each device, the return code will be set to -ENOTRECOVERABLE if we
> > > + * couldn't write something to disk; or the results of the block device flush
> > > + * operation.
> > 
> > Why not -EIO?
> 
> Originally I thought it might be useful to be able to distinguish
> between "dirty buffers never even made it out of the buffer cache" vs.
> "dirty buffers were sent to the disk but the disk sent back media
> errors", though in the end the userspace tools don't make any
> distinction.
> 
> That said, looking at this again, maybe I should track write verifier
> failure separately so that we can return EFSCORRUPTED for that?
> 

It's not clear to me that anything application level would care much
about verifier failure vs. I/O failure, but I've no objection to doing
something like that either.

Brian

> --D
> 
> > 
> > Brian
> > 
> > > + */
> > > +void
> > > +libxfs_flush_devices(
> > > +	struct xfs_mount	*mp,
> > > +	int			*datadev,
> > > +	int			*logdev,
> > > +	int			*rtdev)
> > > +{
> > > +	*datadev = *logdev = *rtdev = 0;
> > > +
> > > +	libxfs_bcache_purge();
> > > +
> > > +	if (mp->m_ddev_targp)
> > > +		*datadev = libxfs_flush_buftarg(mp->m_ddev_targp);
> > > +
> > > +	if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
> > > +		*logdev = libxfs_flush_buftarg(mp->m_logdev_targp);
> > > +
> > > +	if (mp->m_rtdev_targp)
> > > +		*rtdev = libxfs_flush_buftarg(mp->m_rtdev_targp);
> > > +}
> > > +
> > >  /*
> > >   * Release any resource obtained during a mount.
> > >   */
> > > diff --git a/libxfs/libxfs_io.h b/libxfs/libxfs_io.h
> > > index 579df52b..fc0fd060 100644
> > > --- a/libxfs/libxfs_io.h
> > > +++ b/libxfs/libxfs_io.h
> > > @@ -23,10 +23,12 @@ struct xfs_perag;
> > >  struct xfs_buftarg {
> > >  	struct xfs_mount	*bt_mount;
> > >  	dev_t			dev;
> > > +	bool			lost_writes;
> > >  };
> > >  
> > >  extern void	libxfs_buftarg_init(struct xfs_mount *mp, dev_t ddev,
> > >  				    dev_t logdev, dev_t rtdev);
> > > +int libxfs_blkdev_issue_flush(struct xfs_buftarg *btp);
> > >  
> > >  #define LIBXFS_BBTOOFF64(bbs)	(((xfs_off_t)(bbs)) << BBSHIFT)
> > >  
> > > diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
> > > index 8b47d438..92e497f9 100644
> > > --- a/libxfs/rdwr.c
> > > +++ b/libxfs/rdwr.c
> > > @@ -17,6 +17,7 @@
> > >  #include "xfs_inode_fork.h"
> > >  #include "xfs_inode.h"
> > >  #include "xfs_trans.h"
> > > +#include "libfrog/platform.h"
> > >  
> > >  #include "libxfs.h"		/* for LIBXFS_EXIT_ON_FAILURE */
> > >  
> > > @@ -1227,9 +1228,11 @@ libxfs_brelse(
> > >  
> > >  	if (!bp)
> > >  		return;
> > > -	if (bp->b_flags & LIBXFS_B_DIRTY)
> > > +	if (bp->b_flags & LIBXFS_B_DIRTY) {
> > >  		fprintf(stderr,
> > >  			"releasing dirty buffer to free list!\n");
> > > +		bp->b_target->lost_writes = true;
> > > +	}
> > >  
> > >  	pthread_mutex_lock(&xfs_buf_freelist.cm_mutex);
> > >  	list_add(&bp->b_node.cn_mru, &xfs_buf_freelist.cm_list);
> > > @@ -1248,9 +1251,11 @@ libxfs_bulkrelse(
> > >  		return 0 ;
> > >  
> > >  	list_for_each_entry(bp, list, b_node.cn_mru) {
> > > -		if (bp->b_flags & LIBXFS_B_DIRTY)
> > > +		if (bp->b_flags & LIBXFS_B_DIRTY) {
> > >  			fprintf(stderr,
> > >  				"releasing dirty buffer (bulk) to free list!\n");
> > > +			bp->b_target->lost_writes = true;
> > > +		}
> > >  		count++;
> > >  	}
> > >  
> > > @@ -1479,6 +1484,24 @@ libxfs_irele(
> > >  	kmem_cache_free(xfs_inode_zone, ip);
> > >  }
> > >  
> > > +/*
> > > + * Flush everything dirty in the kernel and disk write caches to stable media.
> > > + * Returns 0 for success or a negative error code.
> > > + */
> > > +int
> > > +libxfs_blkdev_issue_flush(
> > > +	struct xfs_buftarg	*btp)
> > > +{
> > > +	int			fd, ret;
> > > +
> > > +	if (btp->dev == 0)
> > > +		return 0;
> > > +
> > > +	fd = libxfs_device_to_fd(btp->dev);
> > > +	ret = platform_flush_device(fd, btp->dev);
> > > +	return ret ? -errno : 0;
> > > +}
> > > +
> > >  /*
> > >   * Write out a buffer list synchronously.
> > >   *
> > > 
> > 
> 


^ permalink raw reply

* [PATCH 0/2] sunxi: clean up defconfig files
From: Maxime Ripard @ 2020-02-20 17:58 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <20200220175115.76632-1-andre.przywara@arm.com>

On Thu, Feb 20, 2020 at 05:51:13PM +0000, Andre Przywara wrote:
> With some recent additions and some old cruft, there are some config
> options that were defined in *almost* every board defconfig file for
> Allwinner SoCs.
> This "almost" seems to point to bugs, either those options were missed by
> mistake or failed to properly synchronise (when a new board defconfig
> comes into the tree and just missed some automatic update).
>
> This series defines those common symbols in their respective Kconfig
> files or in the ARCH_SUNXI definition, then removes them from all the
> defconfigs.
>
> This fixes those boards that suffered from a missing definition, also
> cleans up all board defconfigs by moving not-board-specific options out
> of there.
>
> Rationale for why those options are generic are given in the commit
> message of 1/2.

defconfig handling really is a pain, thanks for taking care of this

Acked-by: Maxime Ripard <mripard@kernel.org>
Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200220/9106e6e5/attachment.sig>

^ permalink raw reply

* Re: [yocto] [psplash][PATCH 1/1] psplash-fb: Avoid racing issues on reading fb0
From: Andrei Gherzan @ 2020-02-20 17:58 UTC (permalink / raw)
  To: Khem Raj; +Cc: yocto
In-Reply-To: <6f979b87-756e-207f-0500-a83c6afa07f6@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1549 bytes --]

Hi,

On Fri, Feb 14, 2020 at 7:32 AM Khem Raj <raj.khem@gmail.com> wrote:

> On 2/13/20 2:30 AM, Andrei Gherzan wrote:
> > When starting psplash as early as possible in the boot process, the fb
> > device node might not be ready. This patch adds a loop on reading the
> > fb0 device with a timeout of 5 seconds.
> >
> > Signed-off-by: Andrei Gherzan <andrei@gherzan.ro>
> > ---
> >   psplash-fb.c | 5 ++++-
> >   1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/psplash-fb.c b/psplash-fb.c
> > index 6603572..6700a3b 100644
> > --- a/psplash-fb.c
> > +++ b/psplash-fb.c
> > @@ -137,6 +137,7 @@ psplash_fb_new (int angle, int fbdev_id)
> >     struct fb_fix_screeninfo fb_fix;
> >     int                      off;
> >     char                     fbdev[9] = "/dev/fb0";
> > +  int retries = 0;
> >
> >     PSplashFB *fb = NULL;
> >
> > @@ -156,7 +157,9 @@ psplash_fb_new (int angle, int fbdev_id)
> >
> >     fb->fd = -1;
> >
> > -  if ((fb->fd = open (fbdev, O_RDWR)) < 0)
> > +  while ((fb->fd = open(fbdev, O_RDWR)) < 0 && retries++ <= 100)
> > +       usleep(50000);
> > +  if (fb->fd < 0)
>
> i wonder if there should be a different way to ensure this dependency
> perhaps sd_notify for systemd or udev notification maybe ..
>

That makes sense. The only issue is that in my use-case, initramfs doesn't
have systemd. And usually, you will be wanting to run a splash way before
any init system. What is your proposal with udev notifications? Can you
expand that?

Regards,
Andrei

[-- Attachment #2: Type: text/html, Size: 2220 bytes --]

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.