diff --git a/device/main/u-boot-pinephone/0014-common-expose-DRAM-clock-speed.patch b/device/main/u-boot-pinephone/0001-common-expose-DRAM-clock-speed.patch similarity index 100% rename from device/main/u-boot-pinephone/0014-common-expose-DRAM-clock-speed.patch rename to device/main/u-boot-pinephone/0001-common-expose-DRAM-clock-speed.patch diff --git a/device/main/u-boot-pinephone/0001-sunxi-DT-H6-update-device-tree-files.patch b/device/main/u-boot-pinephone/0001-sunxi-DT-H6-update-device-tree-files.patch deleted file mode 100644 index e8d9e0fae..000000000 --- a/device/main/u-boot-pinephone/0001-sunxi-DT-H6-update-device-tree-files.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 599896bc50b4532f39105ed0c40ada838227650d Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Thu, 7 May 2020 18:50:37 -0500 -Subject: [PATCH 01/10] sunxi: DT: H6: update device tree files - -Import updated device trees from Linux v5.9. - -Signed-off-by: Samuel Holland ---- - arch/arm/dts/Makefile | 1 + - arch/arm/dts/sun50i-h6-pine-h64-model-b.dts | 21 +++++++++++++++++++++ - 2 files changed, 22 insertions(+) - create mode 100644 arch/arm/dts/sun50i-h6-pine-h64-model-b.dts - -diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile -index fc16a57e60..de2e4ca66b 100644 ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -642,6 +642,7 @@ dtb-$(CONFIG_MACH_SUN50I_H6) += \ - sun50i-h6-orangepi-lite2.dtb \ - sun50i-h6-orangepi-one-plus.dtb \ - sun50i-h6-pine-h64.dtb \ -+ sun50i-h6-pine-h64-model-b.dtb \ - sun50i-h6-tanix-tx6.dtb - dtb-$(CONFIG_MACH_SUN50I_H616) += \ - sun50i-h616-orangepi-zero2.dtb -diff --git a/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts b/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts -new file mode 100644 -index 0000000000..f4c8966a64 ---- /dev/null -+++ b/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts -@@ -0,0 +1,21 @@ -+// SPDX-License-Identifier: (GPL-2.0+ or MIT) -+/* -+ * Copyright (C) 2019 Corentin LABBE -+ */ -+ -+#include "sun50i-h6-pine-h64.dts" -+ -+/ { -+ model = "Pine H64 model B"; -+ compatible = "pine64,pine-h64-model-b", "allwinner,sun50i-h6"; -+ -+ /delete-node/ reg_gmac_3v3; -+}; -+ -+&hdmi_connector { -+ /delete-property/ ddc-en-gpios; -+}; -+ -+&emac { -+ phy-supply = <®_aldo2>; -+}; --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0009-disable-bootdelay.patch b/device/main/u-boot-pinephone/0002-disable-bootdelay.patch similarity index 78% rename from device/main/u-boot-pinephone/0009-disable-bootdelay.patch rename to device/main/u-boot-pinephone/0002-disable-bootdelay.patch index 7b6a09ecb..8b78dde39 100644 --- a/device/main/u-boot-pinephone/0009-disable-bootdelay.patch +++ b/device/main/u-boot-pinephone/0002-disable-bootdelay.patch @@ -8,14 +8,17 @@ Subject: [PATCH 09/10] disable bootdelay 1 file changed, 1 insertion(+) diff --git a/configs/pinephone_defconfig b/configs/pinephone_defconfig -index 149772749a..1683c1f032 100644 +index 9d39204a43..1f0ce680f9 100644 --- a/configs/pinephone_defconfig +++ b/configs/pinephone_defconfig -@@ -11,3 +11,4 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +@@ -11,6 +11,7 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_PINEPHONE_DT_SELECTION=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_OF_LIST="sun50i-a64-pinephone-1.1 sun50i-a64-pinephone-1.2" +CONFIG_BOOTDELAY=0 --- + CONFIG_LED_STATUS=y + CONFIG_LED_STATUS_GPIO=y + CONFIG_LED_STATUS0=y +-- 2.31.1 diff --git a/device/main/u-boot-pinephone/0002-tools-mkimage-Add-Allwinner-TOC0-support.patch b/device/main/u-boot-pinephone/0002-tools-mkimage-Add-Allwinner-TOC0-support.patch deleted file mode 100644 index b8a4d27e7..000000000 --- a/device/main/u-boot-pinephone/0002-tools-mkimage-Add-Allwinner-TOC0-support.patch +++ /dev/null @@ -1,995 +0,0 @@ -From 0db85bb77ddc1dad6b2cb24b105274f6a77e4fc7 Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Sun, 20 Jun 2021 14:09:29 -0500 -Subject: [PATCH 02/10] tools: mkimage: Add Allwinner TOC0 support - -Most Allwinner sunxi SoCs have separate boot ROMs in non-secure and -secure mode. The non-secure boot ROM (NBROM) uses the existing -sunxi_egon image type. The secure boot ROM (SBROM) uses a completely -different image type, known as TOC0. - -A TOC0 image is composed of a header and two or more items. These items -include signed firmware and a key chain linking to a root-of-trust -public key (ROTPK) hash burned to eFuses in the SoC. Signatures are made -using RSA-2048 + SHA256. - -This TOC0 implementation has been verified to work with the A64, H5, H6, -and H616 SBROMs. - -Signed-off-by: Samuel Holland ---- - common/image.c | 1 + - include/image.h | 1 + - include/sunxi_image.h | 191 ++++++++++++ - tools/Makefile | 3 +- - tools/sunxi_toc0.c | 710 ++++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 905 insertions(+), 1 deletion(-) - create mode 100644 tools/sunxi_toc0.c - -diff --git a/common/image.c b/common/image.c -index 59c52a1f9a..8f1634c120 100644 ---- a/common/image.c -+++ b/common/image.c -@@ -191,6 +191,7 @@ static const table_entry_t uimage_type[] = { - { IH_TYPE_MTKIMAGE, "mtk_image", "MediaTek BootROM loadable Image" }, - { IH_TYPE_COPRO, "copro", "Coprocessor Image"}, - { IH_TYPE_SUNXI_EGON, "sunxi_egon", "Allwinner eGON Boot Image" }, -+ { IH_TYPE_SUNXI_TOC0, "sunxi_toc0", "Allwinner TOC0 Boot Image" }, - { -1, "", "", }, - }; - -diff --git a/include/image.h b/include/image.h -index 73a763a693..7913753c01 100644 ---- a/include/image.h -+++ b/include/image.h -@@ -262,6 +262,7 @@ enum { - IH_TYPE_IMX8IMAGE, /* Freescale IMX8Boot Image */ - IH_TYPE_COPRO, /* Coprocessor Image for remoteproc*/ - IH_TYPE_SUNXI_EGON, /* Allwinner eGON Boot Image */ -+ IH_TYPE_SUNXI_TOC0, /* Allwinner TOC0 Boot Image */ - - IH_TYPE_COUNT, /* Number of image types */ - }; -diff --git a/include/sunxi_image.h b/include/sunxi_image.h -index 5b2055c0af..bdf80ec0e0 100644 ---- a/include/sunxi_image.h -+++ b/include/sunxi_image.h -@@ -9,9 +9,12 @@ - * - * Shared between mkimage and the SPL. - */ -+ - #ifndef SUNXI_IMAGE_H - #define SUNXI_IMAGE_H - -+#include -+ - #define BOOT0_MAGIC "eGON.BT0" - #define BROM_STAMP_VALUE 0x5f0a6c39 - #define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */ -@@ -79,4 +82,192 @@ struct boot_file_head { - /* Compile time check to assure proper alignment of structure */ - typedef char boot_file_head_not_multiple_of_32[1 - 2*(sizeof(struct boot_file_head) % 32)]; - -+struct toc0_main_info { -+ uint8_t name[8]; -+ __le32 magic; -+ __le32 checksum; -+ __le32 serial; -+ __le32 status; -+ __le32 num_items; -+ __le32 length; -+ uint8_t platform[4]; -+ uint8_t reserved[8]; -+ uint8_t end[4]; -+}; -+ -+#define TOC0_MAIN_INFO_NAME "TOC0.GLH" -+#define TOC0_MAIN_INFO_MAGIC 0x89119800 -+#define TOC0_MAIN_INFO_END "MIE;" -+ -+struct toc0_item_info { -+ __le32 name; -+ __le32 offset; -+ __le32 length; -+ __le32 status; -+ __le32 type; -+ __le32 load_addr; -+ uint8_t reserved[4]; -+ uint8_t end[4]; -+}; -+ -+#define TOC0_ITEM_INFO_NAME_CERT 0x00010101 -+#define TOC0_ITEM_INFO_NAME_FIRMWARE 0x00010202 -+#define TOC0_ITEM_INFO_NAME_KEY 0x00010303 -+#define TOC0_ITEM_INFO_END "IIE;" -+ -+struct toc0_small_tag { -+ uint8_t tag; -+ uint8_t length; -+}; -+ -+typedef struct toc0_small_tag toc0_small_int; -+typedef struct toc0_small_tag toc0_small_oct; -+typedef struct toc0_small_tag toc0_small_seq; -+typedef struct toc0_small_tag toc0_small_exp; -+ -+#define TOC0_SMALL_INT(len) { 0x02, (len) } -+#define TOC0_SMALL_SEQ(len) { 0x30, (len) } -+#define TOC0_SMALL_EXP(tag, len) { 0xa0 | (tag), len } -+ -+struct toc0_large_tag { -+ uint8_t tag; -+ uint8_t prefix; -+ uint8_t length_hi; -+ uint8_t length_lo; -+}; -+ -+typedef struct toc0_large_tag toc0_large_int; -+typedef struct toc0_large_tag toc0_large_bit; -+typedef struct toc0_large_tag toc0_large_seq; -+ -+#define TOC0_LARGE_INT(len) { 0x02, 0x82, (len) >> 8, (len) & 0xff } -+#define TOC0_LARGE_BIT(len) { 0x03, 0x82, (len) >> 8, (len) & 0xff } -+#define TOC0_LARGE_SEQ(len) { 0x30, 0x82, (len) >> 8, (len) & 0xff } -+ -+/* -+ * This looks somewhat like an X.509 certificate, but it is not valid BER. -+ * -+ * Some differences: -+ * - Some X.509 certificate fields are missing or rearranged. -+ * - Some sequences have the wrong tag. -+ * - Zero-length sequences are accepted. -+ * - Large strings and integers must be an even number of bytes long. -+ * - Positive integers are not zero-extended to maintain their sign. -+ * -+ * See https://linux-sunxi.org/TOC0 for more information. -+ */ -+struct toc0_cert_item { -+ toc0_large_seq tag_totalSequence; -+ struct toc0_totalSequence { -+ toc0_large_seq tag_mainSequence; -+ struct toc0_mainSequence { -+ toc0_small_exp tag_explicit0; -+ struct toc0_explicit0 { -+ toc0_small_int tag_version; -+ uint8_t version; -+ } explicit0; -+ toc0_small_int tag_serialNumber; -+ uint8_t serialNumber; -+ toc0_small_seq tag_signature; -+ toc0_small_seq tag_issuer; -+ toc0_small_seq tag_validity; -+ toc0_small_seq tag_subject; -+ toc0_large_seq tag_subjectPublicKeyInfo; -+ struct toc0_subjectPublicKeyInfo { -+ toc0_small_seq tag_algorithm; -+ toc0_large_seq tag_publicKey; -+ struct toc0_publicKey { -+ toc0_large_int tag_n; -+ uint8_t n[256]; -+ toc0_small_int tag_e; -+ uint8_t e[3]; -+ } publicKey; -+ } subjectPublicKeyInfo; -+ toc0_small_exp tag_explicit3; -+ struct toc0_explicit3 { -+ toc0_small_seq tag_extension; -+ struct toc0_extension { -+ toc0_small_int tag_digest; -+ uint8_t digest[32]; -+ } extension; -+ } explicit3; -+ } mainSequence; -+ toc0_large_bit tag_sigSequence; -+ struct toc0_sigSequence { -+ toc0_small_seq tag_algorithm; -+ toc0_large_bit tag_signature; -+ uint8_t signature[256]; -+ } sigSequence; -+ } totalSequence; -+}; -+ -+#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) -+ -+#define TOC0_CERT_ITEM { \ -+ TOC0_LARGE_SEQ(sizeof(struct toc0_totalSequence)), \ -+ { \ -+ TOC0_LARGE_SEQ(sizeof(struct toc0_mainSequence)), \ -+ { \ -+ TOC0_SMALL_EXP(0, sizeof(struct toc0_explicit0)), \ -+ { \ -+ TOC0_SMALL_INT(sizeof_field(struct toc0_explicit0, version)), \ -+ 0, \ -+ }, \ -+ TOC0_SMALL_INT(sizeof_field(struct toc0_mainSequence, serialNumber)), \ -+ 0, \ -+ TOC0_SMALL_SEQ(0), \ -+ TOC0_SMALL_SEQ(0), \ -+ TOC0_SMALL_SEQ(0), \ -+ TOC0_SMALL_SEQ(0), \ -+ TOC0_LARGE_SEQ(sizeof(struct toc0_subjectPublicKeyInfo)), \ -+ { \ -+ TOC0_SMALL_SEQ(0), \ -+ TOC0_LARGE_SEQ(sizeof(struct toc0_publicKey)), \ -+ { \ -+ TOC0_LARGE_INT(sizeof_field(struct toc0_publicKey, n)), \ -+ {}, \ -+ TOC0_SMALL_INT(sizeof_field(struct toc0_publicKey, e)), \ -+ {}, \ -+ }, \ -+ }, \ -+ TOC0_SMALL_EXP(3, sizeof(struct toc0_explicit3)), \ -+ { \ -+ TOC0_SMALL_SEQ(sizeof(struct toc0_extension)), \ -+ { \ -+ TOC0_SMALL_INT(sizeof_field(struct toc0_extension, digest)), \ -+ {}, \ -+ }, \ -+ }, \ -+ }, \ -+ TOC0_LARGE_BIT(sizeof(struct toc0_sigSequence)), \ -+ { \ -+ TOC0_SMALL_SEQ(0), \ -+ TOC0_LARGE_BIT(sizeof_field(struct toc0_sigSequence, signature)), \ -+ {}, \ -+ }, \ -+ }, \ -+} -+ -+struct toc0_key_item { -+ __le32 vendor_id; -+ __le32 key0_n_len; -+ __le32 key0_e_len; -+ __le32 key1_n_len; -+ __le32 key1_e_len; -+ __le32 sig_len; -+ uint8_t key0[512]; -+ uint8_t key1[512]; -+ uint8_t reserved[32]; -+ uint8_t sig[256]; -+}; -+ -+#define TOC0_DEFAULT_NUM_ITEMS 3 -+#define TOC0_DEFAULT_HEADER_LEN \ -+ ALIGN( \ -+ sizeof(struct toc0_main_info) + \ -+ sizeof(struct toc0_item_info) * TOC0_DEFAULT_NUM_ITEMS + \ -+ sizeof(struct toc0_cert_item) + \ -+ sizeof(struct toc0_key_item), \ -+ 32) -+ - #endif -diff --git a/tools/Makefile b/tools/Makefile -index 4a86321f64..46a4f9c0f1 100644 ---- a/tools/Makefile -+++ b/tools/Makefile -@@ -96,7 +96,8 @@ AES_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix lib/aes/, \ - - # Cryptographic helpers that depend on openssl/libcrypto - LIBCRYPTO_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix lib/, \ -- fdt-libcrypto.o) -+ fdt-libcrypto.o)\ -+ sunxi_toc0.o \ - - ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o - -diff --git a/tools/sunxi_toc0.c b/tools/sunxi_toc0.c -new file mode 100644 -index 0000000000..f0bf86b477 ---- /dev/null -+++ b/tools/sunxi_toc0.c -@@ -0,0 +1,710 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * (C) Copyright 2018 Arm Ltd. -+ * (C) Copyright 2020-2021 Samuel Holland -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "imagetool.h" -+#include "mkimage.h" -+ -+/* -+ * NAND requires 8K padding. For other devices, BROM requires only -+ * 512B padding, but let's use the larger padding to cover everything. -+ */ -+#define PAD_SIZE 8192 -+ -+#define pr_err(fmt, args...) fprintf(stderr, "TOC0 ERR: " fmt, ##args) -+#define pr_warn(fmt, args...) fprintf(stderr, "TOC0 WRN: " fmt, ##args) -+#define pr_info(fmt, args...) fprintf(stderr, "TOC0 INF: " fmt, ##args) -+ -+static char *fw_key_file = "fw_key.pem"; -+static char *key_item_file = "key_item.bin"; -+static char *root_key_file = "root_key.pem"; -+ -+/* -+ * Create a key item in @buf, containing the public keys @root_key and @fw_key, -+ * and signed by the RSA key @root_key. -+ */ -+static int toc0_create_key_item(uint8_t *buf, uint32_t *len, -+ RSA *root_key, RSA *fw_key) -+{ -+ struct toc0_key_item *key_item = (void *)buf; -+ uint8_t digest[SHA256_DIGEST_LENGTH]; -+ int ret = EXIT_FAILURE; -+ unsigned int sig_len; -+ int n_len, e_len; -+ -+ /* Store key 0. */ -+ n_len = BN_bn2bin(RSA_get0_n(root_key), key_item->key0); -+ e_len = BN_bn2bin(RSA_get0_e(root_key), key_item->key0 + n_len); -+ if (n_len + e_len > sizeof(key_item->key0)) { -+ pr_err("Root key is too large\n"); -+ goto err; -+ } -+ key_item->key0_n_len = cpu_to_le32(n_len); -+ key_item->key0_e_len = cpu_to_le32(e_len); -+ -+ /* Store key 1. */ -+ n_len = BN_bn2bin(RSA_get0_n(fw_key), key_item->key1); -+ e_len = BN_bn2bin(RSA_get0_e(fw_key), key_item->key1 + n_len); -+ if (n_len + e_len > sizeof(key_item->key1)) { -+ pr_err("Firmware key is too large\n"); -+ goto err; -+ } -+ key_item->key1_n_len = cpu_to_le32(n_len); -+ key_item->key1_e_len = cpu_to_le32(e_len); -+ -+ /* Sign the key item. */ -+ key_item->sig_len = cpu_to_le32(RSA_size(root_key)); -+ SHA256(buf, key_item->sig - buf, digest); -+ if (!RSA_sign(NID_sha256, digest, sizeof(digest), -+ key_item->sig, &sig_len, root_key)) { -+ pr_err("Failed to sign key item\n"); -+ goto err; -+ } -+ if (sig_len != sizeof(key_item->sig)) { -+ pr_err("Signature length mismatch\n"); -+ goto err; -+ } -+ -+ *len = sizeof(*key_item); -+ ret = EXIT_SUCCESS; -+ -+err: -+ return ret; -+} -+ -+/* -+ * Verify the key item in @buf, containing two public keys @key0 and @key1, -+ * and signed by the RSA key @key0. If @root_key is provided, only signatures -+ * by that key will be accepted. @key1 is returned in @key. -+ */ -+static int toc0_verify_key_item(const uint8_t *buf, uint32_t len, -+ RSA *root_key, RSA **fw_key) -+{ -+ struct toc0_key_item *key_item = (void *)buf; -+ uint8_t digest[SHA256_DIGEST_LENGTH]; -+ int ret = EXIT_FAILURE; -+ int n_len, e_len; -+ RSA *key0 = NULL; -+ RSA *key1 = NULL; -+ BIGNUM *n, *e; -+ -+ if (len < sizeof(*key_item)) -+ goto err; -+ -+ /* Load key 0. */ -+ n_len = le32_to_cpu(key_item->key0_n_len); -+ e_len = le32_to_cpu(key_item->key0_e_len); -+ if (n_len + e_len > sizeof(key_item->key0)) -+ goto err; -+ n = BN_bin2bn(key_item->key0, n_len, NULL); -+ e = BN_bin2bn(key_item->key0 + n_len, e_len, NULL); -+ key0 = RSA_new(); -+ if (!key0) -+ goto err; -+ if (!RSA_set0_key(key0, n, e, NULL)) -+ goto err; -+ -+ /* If a root key was provided, compare it to key 0. */ -+ if (root_key && (BN_cmp(n, RSA_get0_n(root_key)) || -+ BN_cmp(e, RSA_get0_e(root_key)))) { -+ pr_err("Root key mismatch\n"); -+ goto err; -+ } -+ -+ /* Verify the key item signature. */ -+ SHA256(buf, key_item->sig - buf, digest); -+ if (!RSA_verify(NID_sha256, digest, sizeof(digest), -+ key_item->sig, le32_to_cpu(key_item->sig_len), key0)) { -+ pr_err("Bad key item signature\n"); -+ goto err; -+ } -+ -+ if (fw_key) { -+ /* Load key 1. */ -+ n_len = le32_to_cpu(key_item->key1_n_len); -+ e_len = le32_to_cpu(key_item->key1_e_len); -+ if (n_len + e_len > sizeof(key_item->key1)) -+ goto err; -+ n = BN_bin2bn(key_item->key1, n_len, NULL); -+ e = BN_bin2bn(key_item->key1 + n_len, e_len, NULL); -+ key1 = RSA_new(); -+ if (!key1) -+ goto err; -+ if (!RSA_set0_key(key1, n, e, NULL)) -+ goto err; -+ -+ if (*fw_key) { -+ /* If a FW key was provided, compare it to key 1. */ -+ if (BN_cmp(n, RSA_get0_n(*fw_key)) || -+ BN_cmp(e, RSA_get0_e(*fw_key))) { -+ pr_err("Firmware key mismatch\n"); -+ goto err; -+ } -+ } else { -+ /* Otherwise, send key1 back to the caller. */ -+ *fw_key = key1; -+ key1 = NULL; -+ } -+ } -+ -+ ret = EXIT_SUCCESS; -+ -+err: -+ RSA_free(key0); -+ RSA_free(key1); -+ -+ return ret; -+} -+ -+/* -+ * Create a certificate in @buf, describing the firmware with SHA256 digest -+ * @digest, and signed by the RSA key @fw_key. -+ */ -+static int toc0_create_cert_item(uint8_t *buf, uint32_t *len, RSA *fw_key, -+ uint8_t digest[static SHA256_DIGEST_LENGTH]) -+{ -+ static const struct toc0_cert_item cert_item_template = TOC0_CERT_ITEM; -+ struct toc0_cert_item *cert_item = (void *)buf; -+ uint8_t cert_digest[SHA256_DIGEST_LENGTH]; -+ struct toc0_totalSequence *totalSequence; -+ struct toc0_sigSequence *sigSequence; -+ struct toc0_extension *extension; -+ struct toc0_publicKey *publicKey; -+ int ret = EXIT_FAILURE; -+ unsigned int sig_len; -+ -+ memcpy(cert_item, &cert_item_template, sizeof(*cert_item)); -+ *len = sizeof(*cert_item); -+ -+ /* -+ * Fill in the public key. -+ * -+ * Only 2048-bit RSA keys are supported. Since this uses a fixed-size -+ * structure, it may fail for non-standard exponents. -+ */ -+ totalSequence = &cert_item->totalSequence; -+ publicKey = &totalSequence->mainSequence.subjectPublicKeyInfo.publicKey; -+ if (BN_bn2binpad(RSA_get0_n(fw_key), publicKey->n, sizeof(publicKey->n)) < 0 || -+ BN_bn2binpad(RSA_get0_e(fw_key), publicKey->e, sizeof(publicKey->e)) < 0) { -+ pr_err("Incorrect key size\n"); -+ goto err; -+ } -+ -+ /* Fill in the firmware digest. */ -+ extension = &totalSequence->mainSequence.explicit3.extension; -+ memcpy(&extension->digest, digest, SHA256_DIGEST_LENGTH); -+ -+ /* -+ * Sign the certificate. -+ * -+ * In older SBROM versions (and by default in newer versions), -+ * the last 4 bytes of the certificate are not signed. -+ * -+ * (The buffer passed to SHA256 starts at tag_mainSequence, but -+ * the buffer size does not include the length of that tag.) -+ */ -+ SHA256((uint8_t *)totalSequence, sizeof(struct toc0_mainSequence), -+ cert_digest); -+ sigSequence = &totalSequence->sigSequence; -+ if (!RSA_sign(NID_sha256, cert_digest, SHA256_DIGEST_LENGTH, -+ sigSequence->signature, &sig_len, fw_key)) { -+ pr_err("Failed to sign certificate\n"); -+ goto err; -+ } -+ if (sig_len != sizeof(sigSequence->signature)) { -+ pr_err("Signature length mismatch\n"); -+ goto err; -+ } -+ -+ ret = EXIT_SUCCESS; -+ -+err: -+ return ret; -+} -+ -+/* -+ * Verify the certificate in @buf, describing the firmware with SHA256 digest -+ * @digest, and signed by the RSA key contained within. If @fw_key is provided, -+ * only that key will be accepted. -+ * -+ * This function is only expected to work with images created by mkimage. -+ */ -+static int toc0_verify_cert_item(const uint8_t *buf, uint32_t len, RSA *fw_key, -+ uint8_t digest[static SHA256_DIGEST_LENGTH]) -+{ -+ const struct toc0_cert_item *cert_item = (const void *)buf; -+ uint8_t cert_digest[SHA256_DIGEST_LENGTH]; -+ const struct toc0_totalSequence *totalSequence; -+ const struct toc0_sigSequence *sigSequence; -+ const struct toc0_extension *extension; -+ const struct toc0_publicKey *publicKey; -+ int ret = EXIT_FAILURE; -+ RSA *key = NULL; -+ BIGNUM *n, *e; -+ -+ /* Extract the public key from the certificate. */ -+ totalSequence = &cert_item->totalSequence; -+ publicKey = &totalSequence->mainSequence.subjectPublicKeyInfo.publicKey; -+ n = BN_bin2bn(publicKey->n, sizeof(publicKey->n), NULL); -+ e = BN_bin2bn(publicKey->e, sizeof(publicKey->e), NULL); -+ key = RSA_new(); -+ if (!key) -+ goto err; -+ if (!RSA_set0_key(key, n, e, NULL)) -+ goto err; -+ -+ /* If a key was provided, compare it to the embedded key. */ -+ if (fw_key && (BN_cmp(RSA_get0_n(key), RSA_get0_n(fw_key)) || -+ BN_cmp(RSA_get0_e(key), RSA_get0_e(fw_key)))) { -+ pr_err("Firmware key mismatch\n"); -+ goto err; -+ } -+ -+ /* If a digest was provided, compare it to the embedded digest. */ -+ extension = &totalSequence->mainSequence.explicit3.extension; -+ if (digest && memcmp(&extension->digest, digest, SHA256_DIGEST_LENGTH)) { -+ pr_err("Firmware digest mismatch\n"); -+ goto err; -+ } -+ -+ /* Verify the certificate's signature. See the comment above. */ -+ SHA256((uint8_t *)totalSequence, sizeof(struct toc0_mainSequence), -+ cert_digest); -+ sigSequence = &totalSequence->sigSequence; -+ if (!RSA_verify(NID_sha256, cert_digest, SHA256_DIGEST_LENGTH, -+ sigSequence->signature, -+ sizeof(sigSequence->signature), key)) { -+ pr_err("Bad certificate signature\n"); -+ goto err; -+ } -+ -+ ret = EXIT_SUCCESS; -+ -+err: -+ RSA_free(key); -+ -+ return ret; -+} -+ -+/* -+ * Always create a TOC0 containing 3 items. The extra item will be ignored on -+ * SoCs which do not support it. -+ */ -+static int toc0_create(uint8_t *buf, uint32_t len, RSA *root_key, RSA *fw_key, -+ uint8_t *key_item, uint32_t key_item_len, -+ uint8_t *fw_item, uint32_t fw_item_len, uint32_t fw_addr) -+{ -+ struct toc0_main_info *main = (void *)buf; -+ struct toc0_item_info *item = (void *)(main + 1); -+ uint8_t digest[SHA256_DIGEST_LENGTH]; -+ uint32_t *buf32 = (void *)buf; -+ RSA *orig_fw_key = fw_key; -+ int ret = EXIT_FAILURE; -+ uint32_t checksum = 0; -+ uint32_t item_offset; -+ uint32_t item_length; -+ int i; -+ -+ /* Hash the firmware for inclusion in the certificate. */ -+ SHA256(fw_item, fw_item_len, digest); -+ -+ /* Create the main TOC0 header, containing three items. */ -+ memcpy(main->name, TOC0_MAIN_INFO_NAME, sizeof(main->name)); -+ main->magic = cpu_to_le32(TOC0_MAIN_INFO_MAGIC); -+ main->checksum = cpu_to_le32(BROM_STAMP_VALUE); -+ main->num_items = cpu_to_le32(TOC0_DEFAULT_NUM_ITEMS); -+ memcpy(main->end, TOC0_MAIN_INFO_END, sizeof(main->end)); -+ -+ /* The first item links the ROTPK to the signing key. */ -+ item_offset = sizeof(*main) + TOC0_DEFAULT_NUM_ITEMS * sizeof(*item); -+ /* Using an existing key item avoids needing the root private key. */ -+ if (key_item) { -+ item_length = sizeof(*key_item); -+ if (toc0_verify_key_item(key_item, item_length, -+ root_key, &fw_key)) -+ goto err; -+ memcpy(buf + item_offset, key_item, item_length); -+ } else if (toc0_create_key_item(buf + item_offset, &item_length, -+ root_key, fw_key)) { -+ goto err; -+ } -+ -+ item->name = cpu_to_le32(TOC0_ITEM_INFO_NAME_KEY); -+ item->offset = cpu_to_le32(item_offset); -+ item->length = cpu_to_le32(item_length); -+ memcpy(item->end, TOC0_ITEM_INFO_END, sizeof(item->end)); -+ -+ /* The second item contains a certificate signed by the firmware key. */ -+ item_offset = item_offset + item_length; -+ if (toc0_create_cert_item(buf + item_offset, &item_length, -+ fw_key, digest)) -+ goto err; -+ -+ item++; -+ item->name = cpu_to_le32(TOC0_ITEM_INFO_NAME_CERT); -+ item->offset = cpu_to_le32(item_offset); -+ item->length = cpu_to_le32(item_length); -+ memcpy(item->end, TOC0_ITEM_INFO_END, sizeof(item->end)); -+ -+ /* The third item contains the actual boot code. */ -+ item_offset = ALIGN(item_offset + item_length, 32); -+ item_length = fw_item_len; -+ if (buf + item_offset != fw_item) -+ memmove(buf + item_offset, fw_item, item_length); -+ -+ item++; -+ item->name = cpu_to_le32(TOC0_ITEM_INFO_NAME_FIRMWARE); -+ item->offset = cpu_to_le32(item_offset); -+ item->length = cpu_to_le32(item_length); -+ item->load_addr = cpu_to_le32(fw_addr); -+ memcpy(item->end, TOC0_ITEM_INFO_END, sizeof(item->end)); -+ -+ /* Pad to the required block size with 0xff to be flash-friendly. */ -+ item_offset = item_offset + item_length; -+ item_length = ALIGN(item_offset, PAD_SIZE) - item_offset; -+ memset(buf + item_offset, 0xff, item_length); -+ -+ /* Fill in the total padded file length. */ -+ item_offset = item_offset + item_length; -+ main->length = cpu_to_le32(item_offset); -+ -+ /* Verify enough space was provided when creating the image. */ -+ assert(len >= item_offset); -+ -+ /* Calculate the checksum. Yes, it's that simple. */ -+ for (i = 0; i < item_offset / 4; ++i) -+ checksum += le32_to_cpu(buf32[i]); -+ main->checksum = cpu_to_le32(checksum); -+ -+ ret = EXIT_SUCCESS; -+ -+err: -+ if (fw_key != orig_fw_key) -+ RSA_free(fw_key); -+ -+ return ret; -+} -+ -+static const struct toc0_item_info * -+toc0_find_item(const struct toc0_main_info *main, -+ uint32_t name, uint32_t *offset, uint32_t *length) -+{ -+ const struct toc0_item_info *item = (void *)(main + 1); -+ uint32_t item_offset, item_length; -+ uint32_t num_items, main_length; -+ int i; -+ -+ num_items = le32_to_cpu(main->num_items); -+ main_length = le32_to_cpu(main->length); -+ -+ for (i = 0; i < num_items; ++i, ++item) { -+ if (le32_to_cpu(item->name) != name) -+ continue; -+ -+ item_offset = le32_to_cpu(item->offset); -+ item_length = le32_to_cpu(item->length); -+ -+ if (item_offset > main_length || -+ item_length > main_length - item_offset) -+ continue; -+ -+ *offset = item_offset; -+ *length = item_length; -+ -+ return item; -+ } -+ -+ return NULL; -+} -+ -+static int toc0_verify(const uint8_t *buf, uint32_t len, RSA *root_key) -+{ -+ const struct toc0_main_info *main = (void *)buf; -+ const struct toc0_item_info *item; -+ uint8_t digest[SHA256_DIGEST_LENGTH]; -+ uint32_t main_length = le32_to_cpu(main->length); -+ uint32_t checksum = BROM_STAMP_VALUE; -+ uint32_t *buf32 = (void *)buf; -+ uint32_t length, offset; -+ int ret = EXIT_FAILURE; -+ RSA *fw_key = NULL; -+ int i; -+ -+ if (len < main_length) -+ goto err; -+ -+ /* Verify the main header. */ -+ if (memcmp(main->name, TOC0_MAIN_INFO_NAME, sizeof(main->name))) -+ goto err; -+ if (le32_to_cpu(main->magic) != TOC0_MAIN_INFO_MAGIC) -+ goto err; -+ /* Verify the checksum without modifying the buffer. */ -+ for (i = 0; i < main_length / 4; ++i) -+ checksum += le32_to_cpu(buf32[i]); -+ if (checksum != 2 * le32_to_cpu(main->checksum)) -+ goto err; -+ /* The length must be at least 512 byte aligned. */ -+ if (main_length % 512) -+ goto err; -+ if (memcmp(main->end, TOC0_MAIN_INFO_END, sizeof(main->end))) -+ goto err; -+ -+ /* Verify the key item if present. */ -+ item = toc0_find_item(main, TOC0_ITEM_INFO_NAME_KEY, &offset, &length); -+ if (!item) -+ fw_key = root_key; -+ else if (toc0_verify_key_item(buf + offset, length, root_key, &fw_key)) -+ goto err; -+ -+ /* Hash the firmware to compare with the certificate. */ -+ item = toc0_find_item(main, TOC0_ITEM_INFO_NAME_FIRMWARE, &offset, &length); -+ if (!item) { -+ pr_err("Image does not contain a firmware item\n"); -+ goto err; -+ } -+ SHA256(buf + offset, length, digest); -+ -+ /* Verify the certificate item. */ -+ item = toc0_find_item(main, TOC0_ITEM_INFO_NAME_CERT, &offset, &length); -+ if (!item) { -+ pr_err("Image does not contain a certificate item\n"); -+ goto err; -+ } -+ if (toc0_verify_cert_item(buf + offset, length, fw_key, digest)) -+ goto err; -+ -+ ret = EXIT_SUCCESS; -+ -+err: -+ if (fw_key != root_key) -+ RSA_free(fw_key); -+ -+ return ret; -+} -+ -+static int toc0_check_params(struct image_tool_params *params) -+{ -+ if (!params->dflag) -+ return -EINVAL; -+ -+ if (params->keydir) { -+ asprintf(&fw_key_file, "%s/%s", params->keydir, fw_key_file); -+ asprintf(&key_item_file, "%s/%s", params->keydir, key_item_file); -+ asprintf(&root_key_file, "%s/%s", params->keydir, root_key_file); -+ } -+ -+ return 0; -+} -+ -+static int toc0_verify_header(unsigned char *buf, int image_size, -+ struct image_tool_params *params) -+{ -+ int ret = EXIT_FAILURE; -+ RSA *root_key = NULL; -+ FILE *fp; -+ -+ /* A root public key is optional. */ -+ fp = fopen(root_key_file, "rb"); -+ if (fp) { -+ pr_info("Verifying image with existing root key\n"); -+ root_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); -+ if (!root_key) -+ root_key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); -+ fclose(fp); -+ if (!root_key) { -+ pr_err("Failed to read public key from '%s'\n", -+ root_key_file); -+ goto err; -+ } -+ } -+ -+ ret = toc0_verify(buf, image_size, root_key); -+ -+err: -+ RSA_free(root_key); -+ -+ return ret; -+} -+ -+static const char *toc0_item_name(uint32_t name) -+{ -+ if (name == TOC0_ITEM_INFO_NAME_CERT) -+ return "Certificate"; -+ if (name == TOC0_ITEM_INFO_NAME_FIRMWARE) -+ return "Firmware"; -+ if (name == TOC0_ITEM_INFO_NAME_KEY) -+ return "Key"; -+ return "(unknown)"; -+} -+ -+static void toc0_print_header(const void *buf) -+{ -+ const struct toc0_main_info *main = buf; -+ const struct toc0_item_info *item = (void *)(main + 1); -+ uint32_t head_length, main_length, num_items; -+ uint32_t item_offset, item_length, item_name; -+ int load_addr = -1; -+ int i; -+ -+ num_items = le32_to_cpu(main->num_items); -+ head_length = sizeof(*main) + num_items * sizeof(*item); -+ main_length = le32_to_cpu(main->length); -+ -+ printf("Allwinner TOC0 Image\n" -+ "Size: %d bytes\n" -+ "Contents: %d items\n" -+ " 00000000:%08x Headers\n", -+ main_length, num_items, head_length); -+ -+ for (i = 0; i < num_items; ++i, ++item) { -+ item_offset = le32_to_cpu(item->offset); -+ item_length = le32_to_cpu(item->length); -+ item_name = le32_to_cpu(item->name); -+ -+ if (item_name == TOC0_ITEM_INFO_NAME_FIRMWARE) -+ load_addr = le32_to_cpu(item->load_addr); -+ -+ printf(" %08x:%08x %s\n", -+ item_offset, item_length, -+ toc0_item_name(item_name)); -+ } -+ -+ if (num_items && item_offset + item_length < main_length) { -+ item_offset = item_offset + item_length; -+ item_length = main_length - item_offset; -+ -+ printf(" %08x:%08x Padding\n", -+ item_offset, item_length); -+ } -+ -+ if (load_addr != -1) -+ printf("Load address: 0x%08x\n", load_addr); -+} -+ -+static void toc0_set_header(void *buf, struct stat *sbuf, int ifd, -+ struct image_tool_params *params) -+{ -+ uint32_t key_item_len = 0; -+ uint8_t *key_item = NULL; -+ int ret = EXIT_FAILURE; -+ RSA *root_key = NULL; -+ RSA *fw_key = NULL; -+ FILE *fp; -+ -+ /* Either a key item or the root private key is required. */ -+ fp = fopen(key_item_file, "rb"); -+ if (fp) { -+ pr_info("Creating image using existing key item\n"); -+ key_item_len = sizeof(struct toc0_key_item); -+ key_item = OPENSSL_malloc(key_item_len); -+ if (!key_item || fread(key_item, key_item_len, 1, fp) != 1) { -+ pr_err("Failed to read key item from '%s'\n", -+ root_key_file); -+ goto err; -+ } -+ fclose(fp); -+ fp = NULL; -+ } -+ -+ fp = fopen(root_key_file, "rb"); -+ if (fp) { -+ root_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); -+ if (!root_key) -+ root_key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); -+ fclose(fp); -+ fp = NULL; -+ } -+ -+ /* When using an existing key item, the root key is optional. */ -+ if (!key_item && (!root_key || !RSA_get0_d(root_key))) { -+ pr_err("Failed to read private key from '%s'\n", -+ root_key_file); -+ goto err; -+ } -+ -+ /* The certificate/firmware private key is always required. */ -+ fp = fopen(fw_key_file, "rb"); -+ if (fp) { -+ fw_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); -+ fclose(fp); -+ fp = NULL; -+ } -+ if (!fw_key) { -+ /* If the root key is a private key, it can be used instead. */ -+ if (root_key && RSA_get0_d(root_key)) { -+ pr_info("Using root key as firmware key\n"); -+ fw_key = root_key; -+ } else { -+ pr_err("Failed to read private key from '%s'\n", -+ fw_key_file); -+ goto err; -+ } -+ } -+ -+ /* Warn about potential compatiblity issues. */ -+ if (key_item || fw_key != root_key) -+ pr_warn("Only H6 supports separate root and firmware keys\n"); -+ -+ ret = toc0_create(buf, params->file_size, root_key, fw_key, -+ key_item, key_item_len, -+ buf + TOC0_DEFAULT_HEADER_LEN, -+ params->orig_file_size, params->addr); -+ -+err: -+ OPENSSL_free(key_item); -+ OPENSSL_free(root_key); -+ if (fw_key != root_key) -+ OPENSSL_free(fw_key); -+ if (fp) -+ fclose(fp); -+ -+ if (ret != EXIT_SUCCESS) -+ exit(ret); -+} -+ -+static int toc0_check_image_type(uint8_t type) -+{ -+ return type == IH_TYPE_SUNXI_TOC0 ? 0 : 1; -+} -+ -+static int toc0_vrec_header(struct image_tool_params *params, -+ struct image_type_params *tparams) -+{ -+ tparams->hdr = calloc(tparams->header_size, 1); -+ -+ /* Save off the unpadded data size for SHA256 calculation. */ -+ params->orig_file_size = params->file_size - TOC0_DEFAULT_HEADER_LEN; -+ -+ /* Return padding to 8K blocks. */ -+ return ALIGN(params->file_size, PAD_SIZE) - params->file_size; -+} -+ -+U_BOOT_IMAGE_TYPE( -+ sunxi_toc0, -+ "Allwinner TOC0 Boot Image support", -+ TOC0_DEFAULT_HEADER_LEN, -+ NULL, -+ toc0_check_params, -+ toc0_verify_header, -+ toc0_print_header, -+ toc0_set_header, -+ NULL, -+ toc0_check_image_type, -+ NULL, -+ toc0_vrec_header -+); --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0003-sunxi-Support-both-SPL-image-types.patch b/device/main/u-boot-pinephone/0003-sunxi-Support-both-SPL-image-types.patch deleted file mode 100644 index a269a065d..000000000 --- a/device/main/u-boot-pinephone/0003-sunxi-Support-both-SPL-image-types.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 67097556d368d16917be3590384d8e988266aa59 Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Sun, 20 Jun 2021 14:23:11 -0500 -Subject: [PATCH 03/10] sunxi: Support both SPL image types - -SPL uses the image header to detect the boot device and to find the -offset of U-Boot proper. Since this information is stored differently in -eGON and TOC0 image headers, add code to find the correct value based on -the image type currently in use. - -Signed-off-by: Samuel Holland ---- - arch/arm/include/asm/arch-sunxi/spl.h | 2 -- - arch/arm/mach-sunxi/board.c | 20 ++++++++++++++------ - include/sunxi_image.h | 14 ++++++++++++++ - 3 files changed, 28 insertions(+), 8 deletions(-) - -diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h -index 58cdf806d9..157b11e489 100644 ---- a/arch/arm/include/asm/arch-sunxi/spl.h -+++ b/arch/arm/include/asm/arch-sunxi/spl.h -@@ -19,8 +19,6 @@ - #define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10 - #define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12 - --#define is_boot0_magic(addr) (memcmp((void *)(addr), BOOT0_MAGIC, 8) == 0) -- - uint32_t sunxi_get_boot_device(void); - - #endif -diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c -index d9b04f75fc..bbed5838c1 100644 ---- a/arch/arm/mach-sunxi/board.c -+++ b/arch/arm/mach-sunxi/board.c -@@ -246,10 +246,13 @@ void s_init(void) - - static int sunxi_get_boot_source(void) - { -- if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */ -- return SUNXI_INVALID_BOOT_SOURCE; -+ if (is_egon_image((void *)SPL_ADDR)) -+ return ((struct boot_file_head *)SPL_ADDR)->boot_media; -+ if (is_toc0_image((void *)SPL_ADDR)) -+ return ((struct toc0_main_info *)SPL_ADDR)->platform[0]; - -- return readb(SPL_ADDR + 0x28); -+ /* Not a valid BROM image, so we must have been booted via FEL. */ -+ return SUNXI_INVALID_BOOT_SOURCE; - } - - /* The sunxi internal brom will try to loader external bootloader -@@ -294,13 +297,18 @@ uint32_t sunxi_get_boot_device(void) - return -1; /* Never reached */ - } - -+#define is_toc0_magic(foo) true -+ - #ifdef CONFIG_SPL_BUILD - static u32 sunxi_get_spl_size(void) - { -- if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */ -- return 0; -+ if (is_egon_image((void *)SPL_ADDR)) -+ return ((struct boot_file_head *)SPL_ADDR)->length; -+ if (is_toc0_image((void *)SPL_ADDR)) -+ return ((struct toc0_main_info *)SPL_ADDR)->length; - -- return readl(SPL_ADDR + 0x10); -+ /* Unknown size, so fall back to the default offset. */ -+ return 0; - } - - /* -diff --git a/include/sunxi_image.h b/include/sunxi_image.h -index bdf80ec0e0..b0424b6b7f 100644 ---- a/include/sunxi_image.h -+++ b/include/sunxi_image.h -@@ -270,4 +270,18 @@ struct toc0_key_item { - sizeof(struct toc0_key_item), \ - 32) - -+static inline bool is_egon_image(void *addr) -+{ -+ struct boot_file_head *head = addr; -+ -+ return memcmp(head->magic, BOOT0_MAGIC, 8) == 0; -+} -+ -+static inline bool is_toc0_image(void *addr) -+{ -+ struct toc0_main_info *main = addr; -+ -+ return memcmp(main->name, TOC0_MAIN_INFO_NAME, 8) == 0; -+} -+ - #endif --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0004-sunxi-Support-building-a-SPL-as-a-TOC0-image.patch b/device/main/u-boot-pinephone/0004-sunxi-Support-building-a-SPL-as-a-TOC0-image.patch deleted file mode 100644 index 13be8bfea..000000000 --- a/device/main/u-boot-pinephone/0004-sunxi-Support-building-a-SPL-as-a-TOC0-image.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 02794d97426245146aaec889583e3eea11e80c02 Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Sun, 20 Jun 2021 14:24:29 -0500 -Subject: [PATCH 04/10] sunxi: Support building a SPL as a TOC0 image - -Now that mkimage can generate TOC0 images, and the SPL can interpret -them, hook up the build infrastructure so the user can choose which -image type to build. - -Signed-off-by: Samuel Holland ---- - arch/arm/mach-sunxi/Kconfig | 2 ++ - board/sunxi/Kconfig | 24 ++++++++++++++++++++++++ - scripts/Makefile.spl | 3 ++- - 3 files changed, 28 insertions(+), 1 deletion(-) - create mode 100644 board/sunxi/Kconfig - -diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig -index 49f94f095c..b0191d0080 100644 ---- a/arch/arm/mach-sunxi/Kconfig -+++ b/arch/arm/mach-sunxi/Kconfig -@@ -1091,6 +1091,8 @@ config BLUETOOTH_DT_DEVICE_FIXUP - The used address is "bdaddr" if set, and "ethaddr" with the LSB - flipped elsewise. - -+source "board/sunxi/Kconfig" -+ - endif - - config CHIP_DIP_SCAN -diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig -new file mode 100644 -index 0000000000..c5c0929db5 ---- /dev/null -+++ b/board/sunxi/Kconfig -@@ -0,0 +1,24 @@ -+choice -+ prompt "SPL Image Type" -+ default SUNXI_SPL_IMAGE_EGON -+ -+config SUNXI_SPL_IMAGE_EGON -+ bool "eGON (non-secure)" -+ help -+ Select this option to embed the SPL binary in an eGON.BT0 image, -+ which is compatible with the non-secure boot ROM (NBROM). -+ -+ This is usually the correct option to choose. -+ -+config SUNXI_SPL_IMAGE_TOC0 -+ bool "TOC0 (secure)" -+ help -+ Select this option to embed the SPL binary in a TOC0 image, -+ which is compatible with the secure boot ROM (SBROM). -+ -+endchoice -+ -+config SUNXI_SPL_IMAGE_TYPE -+ string -+ default "sunxi_egon" if SUNXI_SPL_IMAGE_EGON -+ default "sunxi_toc0" if SUNXI_SPL_IMAGE_TOC0 -diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl -index 25a3e7fa52..52ead28487 100644 ---- a/scripts/Makefile.spl -+++ b/scripts/Makefile.spl -@@ -414,7 +414,8 @@ endif - $(obj)/$(SPL_BIN).sfp: $(obj)/$(SPL_BIN).bin FORCE - $(call if_changed,mkimage) - --MKIMAGEFLAGS_sunxi-spl.bin = -T sunxi_egon \ -+MKIMAGEFLAGS_sunxi-spl.bin = -T $(CONFIG_SUNXI_SPL_IMAGE_TYPE) \ -+ -a $(CONFIG_SPL_TEXT_BASE) \ - -n $(CONFIG_DEFAULT_DEVICE_TREE) - - OBJCOPYFLAGS_u-boot-spl-dtb.hex := -I binary -O ihex --change-address=$(CONFIG_SPL_TEXT_BASE) --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0005-sunxi-DT-H6-Add-USB3-to-Pine-H64-DTS.patch b/device/main/u-boot-pinephone/0005-sunxi-DT-H6-Add-USB3-to-Pine-H64-DTS.patch deleted file mode 100644 index 6326418db..000000000 --- a/device/main/u-boot-pinephone/0005-sunxi-DT-H6-Add-USB3-to-Pine-H64-DTS.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 2ebd6418254742499ab6150877879536486b47b3 Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Sat, 17 Apr 2021 14:21:45 -0500 -Subject: [PATCH 05/10] sunxi: DT: H6: Add USB3 to Pine H64 DTS - -Signed-off-by: Samuel Holland ---- - arch/arm/dts/sun50i-h6-pine-h64.dts | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/arch/arm/dts/sun50i-h6-pine-h64.dts b/arch/arm/dts/sun50i-h6-pine-h64.dts -index b868ad17af..73d011dc69 100644 ---- a/arch/arm/dts/sun50i-h6-pine-h64.dts -+++ b/arch/arm/dts/sun50i-h6-pine-h64.dts -@@ -89,6 +89,10 @@ - status = "okay"; - }; - -+&dwc3 { -+ status = "okay"; -+}; -+ - &ehci0 { - status = "okay"; - }; -@@ -332,3 +336,7 @@ - usb3_vbus-supply = <®_usb_vbus>; - status = "okay"; - }; -+ -+&usb3phy { -+ status = "okay"; -+}; --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0006-sunxi-Load-sun8i-secure-monitor-to-SRAM-A2.patch b/device/main/u-boot-pinephone/0006-sunxi-Load-sun8i-secure-monitor-to-SRAM-A2.patch deleted file mode 100644 index 5f11c28ee..000000000 --- a/device/main/u-boot-pinephone/0006-sunxi-Load-sun8i-secure-monitor-to-SRAM-A2.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 40b65e95cfebc9d9af61d3c47562cdeb6b2a1302 Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Sat, 17 Apr 2021 10:43:58 -0500 -Subject: [PATCH 06/10] sunxi: Load sun8i secure monitor to SRAM A2 - -Most sun6i-derived SoCs contain SRAM A2, a secure SRAM area for ARISC -SCP firmware. H3 has a smaller SRAM than other SoCs (A31/A33/A23/A83T). - -On sun8i SoCs which do not have SRAM B, we can use part of this SRAM for -the secure monitor. Follow the design of 64-bit SoCs and use the first -part for the monitor, and the last 16 KiB for the SCP firmware. With -this change, the monitor no longer needs to reserve a region in DRAM. - -Signed-off-by: Samuel Holland ---- - include/configs/sun8i.h | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h -index 27c9808a49..3466c75e28 100644 ---- a/include/configs/sun8i.h -+++ b/include/configs/sun8i.h -@@ -22,6 +22,13 @@ - #define CONFIG_ARMV7_SECURE_MAX_SIZE (SUNXI_SRAM_A2_SIZE - 33 * 1024) - #endif - -+/* -+ * Skip the first 16 KiB of SRAM A2, which is not usable, as only certain bytes -+ * are writable. Reserve the last 17 KiB for the resume shim and SCP firmware. -+ */ -+#define CONFIG_ARMV7_SECURE_BASE (SUNXI_SRAM_A2_BASE + 16 * 1024) -+#define CONFIG_ARMV7_SECURE_MAX_SIZE (SUNXI_SRAM_A2_SIZE - 33 * 1024) -+ - /* - * Include common sunxi configuration where most the settings are - */ --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0007-pinephone-Add-volume_key-environment-variable.patch b/device/main/u-boot-pinephone/0007-pinephone-Add-volume_key-environment-variable.patch deleted file mode 100644 index aee1a29f1..000000000 --- a/device/main/u-boot-pinephone/0007-pinephone-Add-volume_key-environment-variable.patch +++ /dev/null @@ -1,177 +0,0 @@ -From d0af5f5a4fc81e4dcd0b51ad46d8faf01b9ae168 Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Tue, 11 Feb 2020 14:10:05 +0100 -Subject: [PATCH 07/10] pinephone: Add volume_key environment variable - -When the user has a volume key pressed volume_key variable will -contain either value 'down' or 'up', otherwise it will be empty. - -Signed-off-by: Ondrej Jirman ---- - board/sunxi/Makefile | 1 + - board/sunxi/board.c | 18 ++++++++++ - board/sunxi/lradc.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ - board/sunxi/lradc.h | 11 ++++++ - 4 files changed, 111 insertions(+) - create mode 100644 board/sunxi/lradc.c - create mode 100644 board/sunxi/lradc.h - -diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile -index d96b7897b6..a096a5c771 100644 ---- a/board/sunxi/Makefile -+++ b/board/sunxi/Makefile -@@ -12,3 +12,4 @@ obj-$(CONFIG_MACH_SUN4I) += dram_sun4i_auto.o - obj-$(CONFIG_MACH_SUN5I) += dram_sun5i_auto.o - obj-$(CONFIG_MACH_SUN7I) += dram_sun5i_auto.o - obj-$(CONFIG_CHIP_DIP_SCAN) += chip.o -+obj-$(CONFIG_MACH_SUN50I) += lradc.o -diff --git a/board/sunxi/board.c b/board/sunxi/board.c -index 1a46100e40..400cc938dd 100644 ---- a/board/sunxi/board.c -+++ b/board/sunxi/board.c -@@ -46,6 +46,7 @@ - #include - #include - #include -+#include "lradc.h" - - #if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD) - /* So that we can use pin names in Kconfig and sunxi_name_to_gpio() */ -@@ -672,6 +673,12 @@ void sunxi_board_init(void) - { - int power_failed = 0; - -+#ifdef CONFIG_MACH_SUN50I -+ // we init the lradc in SPL to get the ADC started early to have -+ // a valid sample when U-Boot main binary gets executed. -+ lradc_enable(); -+#endif -+ - #ifdef CONFIG_SY8106A_POWER - power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT); - #endif -@@ -946,6 +953,17 @@ int misc_init_r(void) - env_set("fdtfile", str); - } - -+#ifdef CONFIG_MACH_SUN50I -+ int key = lradc_get_pressed_key(); -+ if (key == KEY_VOLUMEDOWN) -+ env_set("volume_key", "down"); -+ else if (key == KEY_VOLUMEUP) -+ env_set("volume_key", "up"); -+ -+ // no longer needed -+ lradc_disable(); -+#endif -+ - setup_environment(gd->fdt_blob); - - return 0; -diff --git a/board/sunxi/lradc.c b/board/sunxi/lradc.c -new file mode 100644 -index 0000000000..693b198e25 ---- /dev/null -+++ b/board/sunxi/lradc.c -@@ -0,0 +1,81 @@ -+#include -+#include -+#include "lradc.h" -+ -+#define LRADC_BASE 0x1c21800 -+ -+#define LRADC_CTRL (LRADC_BASE + 0x00) -+#define LRADC_INTC (LRADC_BASE + 0x04) -+#define LRADC_INTS (LRADC_BASE + 0x08) -+#define LRADC_DATA0 (LRADC_BASE + 0x0c) -+#define LRADC_DATA1 (LRADC_BASE + 0x10) -+ -+/* LRADC_CTRL bits */ -+#define FIRST_CONVERT_DLY(x) ((x) << 24) /* 8 bits */ -+#define CHAN_SELECT(x) ((x) << 22) /* 2 bits */ -+#define CONTINUE_TIME_SEL(x) ((x) << 16) /* 4 bits */ -+#define KEY_MODE_SEL(x) ((x) << 12) /* 2 bits */ -+#define LEVELA_B_CNT(x) ((x) << 8) /* 4 bits */ -+#define HOLD_KEY_EN(x) ((x) << 7) -+#define HOLD_EN(x) ((x) << 6) -+#define LEVELB_VOL(x) ((x) << 4) /* 2 bits */ -+#define SAMPLE_RATE(x) ((x) << 2) /* 2 bits */ -+#define ENABLE(x) ((x) << 0) -+ -+/* LRADC_INTC and LRADC_INTS bits */ -+#define CHAN1_KEYUP_IRQ BIT(12) -+#define CHAN1_ALRDY_HOLD_IRQ BIT(11) -+#define CHAN1_HOLD_IRQ BIT(10) -+#define CHAN1_KEYDOWN_IRQ BIT(9) -+#define CHAN1_DATA_IRQ BIT(8) -+#define CHAN0_KEYUP_IRQ BIT(4) -+#define CHAN0_ALRDY_HOLD_IRQ BIT(3) -+#define CHAN0_HOLD_IRQ BIT(2) -+#define CHAN0_KEYDOWN_IRQ BIT(1) -+#define CHAN0_DATA_IRQ BIT(0) -+ -+// this is for PinePhone only -+ -+int lradc_get_pressed_key(void) -+{ -+ uint32_t val; -+ uint32_t vref = 3000000 * 2 / 3; -+ -+ val = readl(LRADC_DATA0) & 0x3f; -+ val = val * vref / 63; -+ -+// printf("lradc=%u\n", val); -+ -+ if (val < 200000) // 158730 -+ return KEY_VOLUMEUP; -+ else if (val < 400000) // 349206 -+ return KEY_VOLUMEDOWN; -+ -+ return 0; -+} -+ -+void lradc_enable(void) -+{ -+ // aldo3 is always on and defaults to 3V -+ -+ writel(0xffffffff, LRADC_INTS); -+ writel(0, LRADC_INTC); -+ -+ /* -+ * Set sample time to 4 ms / 250 Hz. Wait 2 * 4 ms for key to -+ * stabilize on press, wait (1 + 1) * 4 ms for key release -+ */ -+ writel(FIRST_CONVERT_DLY(0) | LEVELA_B_CNT(0) | HOLD_EN(0) | -+ SAMPLE_RATE(0) | ENABLE(1), LRADC_CTRL); -+ -+} -+ -+void lradc_disable(void) -+{ -+ writel(0xffffffff, LRADC_INTS); -+ writel(0, LRADC_INTC); -+ -+ /* Disable lradc, leave other settings unchanged */ -+ writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) | -+ SAMPLE_RATE(2), LRADC_CTRL); -+} -diff --git a/board/sunxi/lradc.h b/board/sunxi/lradc.h -new file mode 100644 -index 0000000000..c908401b5b ---- /dev/null -+++ b/board/sunxi/lradc.h -@@ -0,0 +1,11 @@ -+#pragma once -+ -+enum { -+ KEY_NONE = 0, -+ KEY_VOLUMEDOWN = 1, -+ KEY_VOLUMEUP = 2, -+}; -+ -+int lradc_get_pressed_key(void); -+void lradc_enable(void); -+void lradc_disable(void); --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0008-Enable-led-on-boot-to-notify-user-of-boot-status.patch b/device/main/u-boot-pinephone/0008-Enable-led-on-boot-to-notify-user-of-boot-status.patch deleted file mode 100644 index a8b9150d4..000000000 --- a/device/main/u-boot-pinephone/0008-Enable-led-on-boot-to-notify-user-of-boot-status.patch +++ /dev/null @@ -1,58 +0,0 @@ -From e7a3da0093b96d89c9d65fe8d5f1dd32f299afa1 Mon Sep 17 00:00:00 2001 -From: Marius Gripsgard -Date: Tue, 5 May 2020 16:51:13 +0200 -Subject: [PATCH 08/10] Enable led on boot to notify user of boot status - ---- - arch/arm/mach-sunxi/Kconfig | 5 +++++ - board/sunxi/board.c | 6 ++++++ - configs/pinephone_defconfig | 1 + - 3 files changed, 12 insertions(+) - -diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig -index b0191d0080..7a46bb4481 100644 ---- a/arch/arm/mach-sunxi/Kconfig -+++ b/arch/arm/mach-sunxi/Kconfig -@@ -1,5 +1,10 @@ - if ARCH_SUNXI - -+config PINEPHONE_LEDS -+ bool "Notify boot status via LEDs on PinePhone" -+ ---help--- -+ LED boot notification. -+ - config SPL_LDSCRIPT - default "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds" if !ARM64 - -diff --git a/board/sunxi/board.c b/board/sunxi/board.c -index 400cc938dd..0abfa78880 100644 ---- a/board/sunxi/board.c -+++ b/board/sunxi/board.c -@@ -679,6 +679,12 @@ void sunxi_board_init(void) - lradc_enable(); - #endif - -+#ifdef CONFIG_PINEPHONE_LEDS -+ /* PD18:G PD19:R PD20:B */ -+ gpio_request(SUNXI_GPD(19), "led:red"); -+ gpio_direction_output(SUNXI_GPD(19), 1); -+#endif -+ - #ifdef CONFIG_SY8106A_POWER - power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT); - #endif -diff --git a/configs/pinephone_defconfig b/configs/pinephone_defconfig -index 64e13d3132..149772749a 100644 ---- a/configs/pinephone_defconfig -+++ b/configs/pinephone_defconfig -@@ -2,6 +2,7 @@ CONFIG_ARM=y - CONFIG_ARCH_SUNXI=y - CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pinephone-1.2" - CONFIG_SPL=y -+CONFIG_PINEPHONE_LEDS=y - CONFIG_MACH_SUN50I=y - CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y - CONFIG_DRAM_CLK=552 --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0010-Reduce-DRAM-speed-to-528-for-better-compatibility-wi.patch b/device/main/u-boot-pinephone/0010-Reduce-DRAM-speed-to-528-for-better-compatibility-wi.patch deleted file mode 100644 index b61d2e177..000000000 --- a/device/main/u-boot-pinephone/0010-Reduce-DRAM-speed-to-528-for-better-compatibility-wi.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 679af1e60220bdb31c42beb41a3a405b23f8ffee Mon Sep 17 00:00:00 2001 -From: Dalton Durst -Date: Wed, 10 Mar 2021 11:44:07 -0600 -Subject: [PATCH 10/10] Reduce DRAM speed to 528 for better compatibility with - all PinePhones - ---- - configs/pinephone_defconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configs/pinephone_defconfig b/configs/pinephone_defconfig -index 1683c1f032..4dde6fec87 100644 ---- a/configs/pinephone_defconfig -+++ b/configs/pinephone_defconfig -@@ -5,7 +5,7 @@ CONFIG_SPL=y - CONFIG_PINEPHONE_LEDS=y - CONFIG_MACH_SUN50I=y - CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y --CONFIG_DRAM_CLK=552 -+CONFIG_DRAM_CLK=528 - CONFIG_DRAM_ZQ=3881949 - CONFIG_MMC_SUNXI_SLOT_EXTRA=2 - CONFIG_PINEPHONE_DT_SELECTION=y --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0011-mmc-sunxi-Add-support-for-DMA-transfers.patch b/device/main/u-boot-pinephone/0011-mmc-sunxi-Add-support-for-DMA-transfers.patch deleted file mode 100644 index 9be832c86..000000000 --- a/device/main/u-boot-pinephone/0011-mmc-sunxi-Add-support-for-DMA-transfers.patch +++ /dev/null @@ -1,354 +0,0 @@ -From b0950e4696b391578f7428337e41fa8ca14b225d Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Wed, 11 Sep 2019 20:45:28 +0200 -Subject: [PATCH 27/29] mmc: sunxi: Add support for DMA transfers - -Allwinner MMC controller supports DMA via internal DMA controller, -use it. - -Signed-off-by: Ondrej Jirman ---- - arch/arm/include/asm/arch-sunxi/mmc.h | 7 + - drivers/mmc/sunxi_mmc.c | 204 +++++++++++++++++++++++--- - 2 files changed, 192 insertions(+), 19 deletions(-) - -diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h -index 5daacf10eb..dc8ea6f43a 100644 ---- a/arch/arm/include/asm/arch-sunxi/mmc.h -+++ b/arch/arm/include/asm/arch-sunxi/mmc.h -@@ -112,6 +112,10 @@ struct sunxi_mmc { - SUNXI_MMC_RINT_COMMAND_DONE | \ - SUNXI_MMC_RINT_VOLTAGE_CHANGE_DONE) - -+#define SUNXI_MMC_FTRGLEVEL_BURST_SIZE(v) (((v) & 0x7) << 28) -+#define SUNXI_MMC_FTRGLEVEL_RX_TL(v) (((v) & 0xfff) << 16) -+#define SUNXI_MMC_FTRGLEVEL_TX_TL(v) (((v) & 0xffff) << 0) -+ - #define SUNXI_MMC_STATUS_RXWL_FLAG (0x1 << 0) - #define SUNXI_MMC_STATUS_TXWL_FLAG (0x1 << 1) - #define SUNXI_MMC_STATUS_FIFO_EMPTY (0x1 << 2) -@@ -130,6 +134,9 @@ struct sunxi_mmc { - #define SUNXI_MMC_IDIE_TXIRQ (0x1 << 0) - #define SUNXI_MMC_IDIE_RXIRQ (0x1 << 1) - -+#define SUNXI_MMC_IDST_TXIRQ (0x1 << 0) -+#define SUNXI_MMC_IDST_RXIRQ (0x1 << 1) -+ - #define SUNXI_MMC_COMMON_CLK_GATE (1 << 16) - #define SUNXI_MMC_COMMON_RESET (1 << 18) - -diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c -index 28af8e6ac5..47c947cdb8 100644 ---- a/drivers/mmc/sunxi_mmc.c -+++ b/drivers/mmc/sunxi_mmc.c -@@ -9,6 +9,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -27,6 +28,27 @@ - #define CCM_MMC_CTRL_MODE_SEL_NEW 0 - #endif - -+#define DMA_CONFIG_DIC BIT(1) // flag: disable interrupt after this descriptor's buffer is processed -+#define DMA_CONFIG_LAST BIT(2) // flag: last descriptor -+#define DMA_CONFIG_FIRST BIT(3) // flag: first descriptor -+#define DMA_CONFIG_CHAIN BIT(4) // flag: buf_addr_ptr2 points to next descriptor -+#define DMA_CONFIG_ERROR BIT(30) // flag: out: error happened -+#define DMA_CONFIG_HOLD BIT(31) // flag: desc owned by IDMAC (set to 1) -+ -+#if defined(CONFIG_MACH_SUN50I) -+// mmc2 on A64 only allows for 8k -+#define DMA_BUF_MAX_SIZE (1 << 13) -+#else -+#define DMA_BUF_MAX_SIZE (1 << 16) -+#endif -+ -+struct sunxi_idma_desc { -+ u32 config; -+ u32 buf_size; -+ u32 buf_addr_ptr1; -+ u32 buf_addr_ptr2; -+}; -+ - struct sunxi_mmc_plat { - struct mmc_config cfg; - struct mmc mmc; -@@ -39,6 +61,8 @@ struct sunxi_mmc_priv { - struct gpio_desc cd_gpio; /* Change Detect GPIO */ - struct sunxi_mmc *reg; - struct mmc_config cfg; -+ unsigned n_dma_descs; -+ struct sunxi_idma_desc* dma_descs; - }; - - #if !CONFIG_IS_ENABLED(DM_MMC) -@@ -318,7 +342,7 @@ static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc, - if (timeout_msecs < 2000) - timeout_msecs = 2000; - -- /* Always read / write data through the CPU */ -+ /* Read / write data through the CPU */ - setbits_le32(&priv->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); - - start = get_timer(0); -@@ -328,7 +352,7 @@ static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc, - - while ((status = readl(&priv->reg->status)) & status_bit) { - if (get_timer(start) > timeout_msecs) -- return -1; -+ return -ETIMEDOUT; - } - - /* -@@ -360,21 +384,142 @@ static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc, - return 0; - } - -+static void flush_cache_auto_align(void* buf, size_t len) -+{ -+ uintptr_t mask = ~((uintptr_t)CONFIG_SYS_CACHELINE_SIZE - 1); -+ uintptr_t start = (uintptr_t)buf & mask; -+ -+ len = (len + 2 * CONFIG_SYS_CACHELINE_SIZE) & mask; -+ -+ flush_cache(start, len); -+} -+ -+static int mmc_trans_data_by_dma(struct sunxi_mmc_priv *priv, struct mmc *mmc, -+ struct mmc_data *data) -+{ -+ const int reading = !!(data->flags & MMC_DATA_READ); -+ uint8_t *buff = (uint8_t*)(reading ? data->dest : data->src); -+ unsigned byte_cnt = data->blocksize * data->blocks; -+ unsigned i, n_desc, last_block_size; -+ u32 rval; -+ -+ /* data pointer and transfer size needs to be aligned to 4 bytes */ -+ -+ /* Read / write data through IDMAC */ -+ clrbits_le32(&priv->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); -+ -+ n_desc = byte_cnt / DMA_BUF_MAX_SIZE; -+ last_block_size = byte_cnt % DMA_BUF_MAX_SIZE; -+ if (last_block_size) -+ n_desc++; -+ -+ if (n_desc > priv->n_dma_descs) -+ return -ENOMEM; -+ -+ memset(priv->dma_descs, 0, sizeof(struct sunxi_idma_desc) * n_desc); -+ -+ for (i = 0; i < n_desc; i++) { -+ struct sunxi_idma_desc* desc = &priv->dma_descs[i]; -+ bool is_last = i == n_desc - 1; -+ bool is_first = i == 0; -+ -+ desc->config = DMA_CONFIG_CHAIN | DMA_CONFIG_HOLD -+ | (is_last ? DMA_CONFIG_LAST : DMA_CONFIG_DIC) -+ | (is_first ? DMA_CONFIG_FIRST : 0); -+ -+ if (is_last && last_block_size) -+ desc->buf_size = last_block_size; -+ else -+ desc->buf_size = DMA_BUF_MAX_SIZE; -+ -+ desc->buf_addr_ptr1 = (uintptr_t)buff + i * DMA_BUF_MAX_SIZE; -+ if (!is_last) -+ desc->buf_addr_ptr2 = (uintptr_t)(desc + 1); -+ } -+ -+ /* -+ * Make sure everyhting needed for a transfer is in DRAM. -+ */ -+ -+ flush_cache_auto_align(buff, byte_cnt); -+ flush_cache_auto_align(priv->dma_descs, -+ sizeof(struct sunxi_idma_desc) * n_desc); -+ -+ dsb(); -+ isb(); -+ -+ /* dma enable */ -+ setbits_le32(&priv->reg->gctrl, SUNXI_MMC_GCTRL_DMA_RESET -+ | SUNXI_MMC_GCTRL_DMA_ENABLE); -+ -+ /* idma reset */ -+ writel(SUNXI_MMC_IDMAC_RESET, &priv->reg->dmac); -+ -+ /* wait idma reset done */ -+ while (readl(&priv->reg->dmac) & SUNXI_MMC_IDMAC_RESET); -+ -+ /* idma on */ -+ writel(SUNXI_MMC_IDMAC_ENABLE | SUNXI_MMC_IDMAC_FIXBURST, -+ &priv->reg->dmac); -+ -+ /* enable interrupt flags */ -+ rval = readl(&priv->reg->idie) -+ & ~(SUNXI_MMC_IDIE_RXIRQ | SUNXI_MMC_IDIE_TXIRQ); -+ rval |= reading ? SUNXI_MMC_IDIE_RXIRQ : SUNXI_MMC_IDIE_TXIRQ; -+ writel(rval, &priv->reg->idie); -+ -+ /* set address of the first descriptor */ -+ writel((uintptr_t)priv->dma_descs, &priv->reg->dlba); -+ -+ /* set fifo fill tresholds for issuing dma */ -+ -+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6) -+ if (priv->mmc_no == 2) { -+ // for mmc 2 we need to set this differently -+ writel(SUNXI_MMC_FTRGLEVEL_BURST_SIZE(3) // burst-16 -+ | SUNXI_MMC_FTRGLEVEL_RX_TL(15) -+ | SUNXI_MMC_FTRGLEVEL_TX_TL(240), -+ &priv->reg->ftrglevel); -+ } else { -+ writel(SUNXI_MMC_FTRGLEVEL_BURST_SIZE(2) // burst-8 -+ | SUNXI_MMC_FTRGLEVEL_RX_TL(7) -+ | SUNXI_MMC_FTRGLEVEL_TX_TL(248), -+ &priv->reg->ftrglevel); -+ } -+#else -+ writel(SUNXI_MMC_FTRGLEVEL_BURST_SIZE(2) // burst-8 -+ | SUNXI_MMC_FTRGLEVEL_RX_TL(7) -+ | SUNXI_MMC_FTRGLEVEL_TX_TL(8), -+ &priv->reg->ftrglevel); -+#endif -+ -+ writel(0xffffffff, &priv->reg->idst); -+ -+ return 0; -+} -+ - static int mmc_rint_wait(struct sunxi_mmc_priv *priv, struct mmc *mmc, -- uint timeout_msecs, uint done_bit, const char *what) -+ uint timeout_msecs, uint done_bit, bool wait_dma, -+ const char *what) - { - unsigned int status; - unsigned long start = get_timer(0); -+ bool dma_done = true; - - do { - status = readl(&priv->reg->rint); -+ - if ((get_timer(start) > timeout_msecs) || - (status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT)) { - debug("%s timeout %x\n", what, - status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT); - return -ETIMEDOUT; - } -- } while (!(status & done_bit)); -+ -+ if (wait_dma) -+ dma_done = readl(&priv->reg->idst) -+ & (SUNXI_MMC_IDST_TXIRQ | SUNXI_MMC_IDST_RXIRQ); -+ } while (!(status & done_bit) || !dma_done); - - return 0; - } -@@ -388,6 +533,7 @@ static int sunxi_mmc_send_cmd_common(struct sunxi_mmc_priv *priv, - int error = 0; - unsigned int status = 0; - unsigned int bytecnt = 0; -+ bool usedma = false; - - if (priv->fatal_err) - return -1; -@@ -424,42 +570,45 @@ static int sunxi_mmc_send_cmd_common(struct sunxi_mmc_priv *priv, - cmd->cmdidx, cmdval | cmd->cmdidx, cmd->cmdarg); - writel(cmd->cmdarg, &priv->reg->arg); - -- if (!data) -- writel(cmdval | cmd->cmdidx, &priv->reg->cmd); -- - /* - * transfer data and check status - * STATREG[2] : FIFO empty - * STATREG[3] : FIFO full - */ - if (data) { -- int ret = 0; -- - bytecnt = data->blocksize * data->blocks; - debug("trans data %d bytes\n", bytecnt); -- writel(cmdval | cmd->cmdidx, &priv->reg->cmd); -- ret = mmc_trans_data_by_cpu(priv, mmc, data); -- if (ret) { -- error = readl(&priv->reg->rint) & -- SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT; -- error = -ETIMEDOUT; -- goto out; -+ -+ if (bytecnt > 64 && !IS_ENABLED(SPL_BUILD)) { -+ debug(" using dma %d\n", bytecnt); -+ error = mmc_trans_data_by_dma(priv, mmc, data); -+ writel(cmdval | cmd->cmdidx, &priv->reg->cmd); -+ usedma = true; -+ } else { -+ debug(" using pio\n"); -+ writel(cmdval | cmd->cmdidx, &priv->reg->cmd); -+ error = mmc_trans_data_by_cpu(priv, mmc, data); - } -+ -+ if (error) -+ goto out; -+ } else { -+ writel(cmdval | cmd->cmdidx, &priv->reg->cmd); - } - - error = mmc_rint_wait(priv, mmc, 1000, SUNXI_MMC_RINT_COMMAND_DONE, -- "cmd"); -+ false, "cmd"); - if (error) - goto out; - - if (data) { -- timeout_msecs = 120; -+ timeout_msecs = 10000; - debug("cacl timeout %x msec\n", timeout_msecs); - error = mmc_rint_wait(priv, mmc, timeout_msecs, - data->blocks > 1 ? - SUNXI_MMC_RINT_AUTO_COMMAND_DONE : - SUNXI_MMC_RINT_DATA_OVER, -- "data"); -+ usedma, "data"); - if (error) - goto out; - } -@@ -491,6 +640,14 @@ static int sunxi_mmc_send_cmd_common(struct sunxi_mmc_priv *priv, - debug("mmc resp 0x%08x\n", cmd->response[0]); - } - out: -+ if (data && usedma) { -+ //status = readl(®->idst); -+ writel(0, &priv->reg->idie); -+ writel(0xffffffff, &priv->reg->idst); -+ writel(0, &priv->reg->dmac); -+ clrbits_le32(&priv->reg->gctrl, SUNXI_MMC_GCTRL_DMA_ENABLE); -+ } -+ - if (error < 0) { - writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl); - mmc_update_clk(priv); -@@ -674,6 +831,15 @@ static int sunxi_mmc_probe(struct udevice *dev) - - priv->reg = dev_read_addr_ptr(dev); - -+ // make sure we have enough space for descritors for BLK_SIZE * b_max -+ priv->n_dma_descs = 512 * 65536 / DMA_BUF_MAX_SIZE; -+ priv->dma_descs = malloc(sizeof(struct sunxi_idma_desc) -+ * priv->n_dma_descs); -+ if (priv->dma_descs == NULL) { -+ debug("init mmc alloc failed\n"); -+ return -ENOMEM; -+ } -+ - /* We don't have a sunxi clock driver so find the clock address here */ - ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0, - 1, &args); --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0012-mmc-sunxi-DDR-DMA-support-for-SPL.patch b/device/main/u-boot-pinephone/0012-mmc-sunxi-DDR-DMA-support-for-SPL.patch deleted file mode 100644 index ed5dae59f..000000000 --- a/device/main/u-boot-pinephone/0012-mmc-sunxi-DDR-DMA-support-for-SPL.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 1af4c86329397bc553122c650226bd5c7acb1ed0 Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Fri, 13 Sep 2019 22:14:43 +0200 -Subject: [PATCH 28/29] mmc: sunxi: DDR/DMA support for SPL - ---- - drivers/mmc/sunxi_mmc.c | 16 +++++++++++++++- - 1 file changed, 15 insertions(+), 1 deletion(-) - -diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c -index 47c947cdb8..855dfd35d9 100644 ---- a/drivers/mmc/sunxi_mmc.c -+++ b/drivers/mmc/sunxi_mmc.c -@@ -579,7 +579,12 @@ static int sunxi_mmc_send_cmd_common(struct sunxi_mmc_priv *priv, - bytecnt = data->blocksize * data->blocks; - debug("trans data %d bytes\n", bytecnt); - -- if (bytecnt > 64 && !IS_ENABLED(SPL_BUILD)) { -+ // DMA doesn't work when the target is SRAM for some reason. -+ int reading = !!(data->flags & MMC_DATA_READ); -+ uint8_t* buf = (uint8_t*)(reading ? data->dest : data->src); -+ bool is_dram = (uintptr_t)buf >= 0x4000000; -+ -+ if (bytecnt > 64 && is_dram) { - debug(" using dma %d\n", bytecnt); - error = mmc_trans_data_by_dma(priv, mmc, data); - writel(cmdval | cmd->cmdidx, &priv->reg->cmd); -@@ -715,10 +720,19 @@ struct mmc *sunxi_mmc_init(int sdc_no) - - cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; - cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; -+ if (sdc_no == 2) -+ cfg->host_caps |= MMC_MODE_DDR_52MHz; - - cfg->f_min = 400000; - cfg->f_max = 52000000; - -+ // enough descs for a realy big u-boot (4MiB) -+ priv->n_dma_descs = 4*1024*1024 / DMA_BUF_MAX_SIZE; -+ priv->dma_descs = malloc(sizeof(struct sunxi_idma_desc) -+ * priv->n_dma_descs); -+ if (priv->dma_descs == NULL) -+ return NULL; -+ - if (mmc_resource_init(sdc_no) != 0) - return NULL; - --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/0013-spl-ARM-Enable-CPU-caches.patch b/device/main/u-boot-pinephone/0013-spl-ARM-Enable-CPU-caches.patch deleted file mode 100644 index efea5c2fc..000000000 --- a/device/main/u-boot-pinephone/0013-spl-ARM-Enable-CPU-caches.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 6ad822cb4d64beda76cade8761c49b55620a8b5b Mon Sep 17 00:00:00 2001 -From: Ondrej Jirman -Date: Tue, 14 Jan 2020 03:56:32 +0100 -Subject: [PATCH 29/29] spl: ARM: Enable CPU caches - -http://u-boot.10912.n7.nabble.com/RFC-PATCH-0-3-spl-Add-D-cache-support-td274750.html - -Signed-off-by: Ondrej Jirman ---- - arch/arm/lib/cache-cp15.c | 29 ++++++++++++++++++++++++ - common/spl/spl.c | 46 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 75 insertions(+) - -diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c -index aab1bf4360..c2fe0acdc4 100644 ---- a/arch/arm/lib/cache-cp15.c -+++ b/arch/arm/lib/cache-cp15.c -@@ -116,6 +116,25 @@ __weak void dram_bank_mmu_setup(int bank) - set_section_dcache(i, DCACHE_DEFAULT_OPTION); - } - -+#if defined(CONFIG_SPL_BUILD) && (defined(CONFIG_SPL_MAX_SIZE) || \ -+ defined(CONFIG_SPL_MAX_FOOTPRINT)) -+__weak void sram_bank_mmu_setup(phys_addr_t start, phys_addr_t size) -+{ -+ int i; -+ -+ for (i = start >> MMU_SECTION_SHIFT; -+ i < (start >> MMU_SECTION_SHIFT) + (size >> MMU_SECTION_SHIFT); -+ i++) -+#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) -+ set_section_dcache(i, DCACHE_WRITETHROUGH); -+#elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC) -+ set_section_dcache(i, DCACHE_WRITEALLOC); -+#else -+ set_section_dcache(i, DCACHE_WRITEBACK); -+#endif -+} -+#endif -+ - /* to activate the MMU we need to set up virtual memory: use 1M areas */ - static inline void mmu_setup(void) - { -@@ -131,6 +150,16 @@ static inline void mmu_setup(void) - dram_bank_mmu_setup(i); - } - -+#if defined(CONFIG_SPL_BUILD) -+#if defined(CONFIG_SPL_MAX_SIZE) -+ sram_bank_mmu_setup(CONFIG_SPL_TEXT_BASE, -+ ALIGN(CONFIG_SPL_MAX_SIZE, MMU_SECTION_SIZE)); -+#elif defined(CONFIG_SPL_MAX_FOOTPRINT) -+ sram_bank_mmu_setup(CONFIG_SPL_TEXT_BASE, -+ ALIGN(CONFIG_SPL_MAX_FOOTPRINT, MMU_SECTION_SIZE)); -+#endif -+#endif -+ - #if defined(CONFIG_ARMV7_LPAE) && __LINUX_ARM_ARCH__ != 4 - /* Set up 4 PTE entries pointing to our 4 1GB page tables */ - for (i = 0; i < 4; i++) { -diff --git a/common/spl/spl.c b/common/spl/spl.c -index a0a608fd77..40c9022928 100644 ---- a/common/spl/spl.c -+++ b/common/spl/spl.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -636,6 +637,35 @@ void board_init_f(ulong dummy) - } - #endif - -+#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \ -+ defined(CONFIG_ARM) -+int reserve_mmu(void) -+{ -+ phys_addr_t ram_top = 0; -+ /* reserve TLB table */ -+ gd->arch.tlb_size = PGTABLE_SIZE; -+ -+#ifdef CONFIG_SYS_SDRAM_BASE -+ ram_top = CONFIG_SYS_SDRAM_BASE; -+#endif -+ ram_top += get_effective_memsize(); -+ gd->arch.tlb_addr = ram_top - gd->arch.tlb_size; -+ debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr, -+ gd->arch.tlb_addr + gd->arch.tlb_size); -+ return 0; -+} -+ -+__weak int dram_init_banksize(void) -+{ -+#if defined(CONFIG_NR_DRAM_BANKS) && defined(CONFIG_SYS_SDRAM_BASE) -+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; -+ gd->bd->bi_dram[0].size = get_effective_memsize(); -+#endif -+ return 0; -+} -+ -+#endif -+ - void board_init_r(gd_t *dummy1, ulong dummy2) - { - u32 spl_boot_list[] = { -@@ -651,6 +681,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2) - debug(">>" SPL_TPL_PROMPT "board_init_r()\n"); - - spl_set_bd(); -+#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \ -+ defined(CONFIG_ARM) -+ dram_init_banksize(); -+ reserve_mmu(); -+ enable_caches(); -+#endif - - #if defined(CONFIG_SYS_SPL_MALLOC_START) - mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START, -@@ -661,6 +697,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2) - if (spl_init()) - hang(); - } -+ if (IS_ENABLED(CONFIG_SPL_ALLOC_BD) && spl_alloc_bd()) { -+ puts("Cannot alloc bd\n"); -+ hang(); -+ } -+ - #if !defined(CONFIG_PPC) && !defined(CONFIG_ARCH_MX6) - /* - * timer_init() does not exist on PPC systems. The timer is initialized -@@ -728,6 +769,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2) - ret); - } - -+#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \ -+ defined(CONFIG_ARM) -+ cleanup_before_linux(); -+#endif -+ - #ifdef CONFIG_CPU_V7M - spl_image.entry_point |= 0x1; - #endif --- -2.31.1 - diff --git a/device/main/u-boot-pinephone/APKBUILD b/device/main/u-boot-pinephone/APKBUILD index 71b817d88..4e618d9d6 100644 --- a/device/main/u-boot-pinephone/APKBUILD +++ b/device/main/u-boot-pinephone/APKBUILD @@ -5,8 +5,8 @@ # Co-Maintainer: Dylan Van Assche # U-boot with patches to make the PinePhone boot faster and have control over the ddr clock speed pkgname=u-boot-pinephone -pkgver=2021.10 -pkgrel=1 +pkgver=2022.07 +pkgrel=0 pkgdesc="U-Boot bootloader for the PINE64 PinePhone" url="https://source.denx.de/u-boot" arch="aarch64" @@ -26,22 +26,10 @@ makedepends="$depends_dev swig " options="!check" -source="http://source.denx.de/u-boot/u-boot/-/archive/v$pkgver/u-boot-v$pkgver.tar.gz +source="https://source.denx.de/u-boot/u-boot/-/archive/v$pkgver/u-boot-v$pkgver.tar.gz update-u-boot - 0001-sunxi-DT-H6-update-device-tree-files.patch - 0002-tools-mkimage-Add-Allwinner-TOC0-support.patch - 0003-sunxi-Support-both-SPL-image-types.patch - 0004-sunxi-Support-building-a-SPL-as-a-TOC0-image.patch - 0005-sunxi-DT-H6-Add-USB3-to-Pine-H64-DTS.patch - 0006-sunxi-Load-sun8i-secure-monitor-to-SRAM-A2.patch - 0007-pinephone-Add-volume_key-environment-variable.patch - 0008-Enable-led-on-boot-to-notify-user-of-boot-status.patch - 0009-disable-bootdelay.patch - 0010-Reduce-DRAM-speed-to-528-for-better-compatibility-wi.patch - 0011-mmc-sunxi-Add-support-for-DMA-transfers.patch - 0012-mmc-sunxi-DDR-DMA-support-for-SPL.patch - 0013-spl-ARM-Enable-CPU-caches.patch - 0014-common-expose-DRAM-clock-speed.patch + 0001-common-expose-DRAM-clock-speed.patch + 0002-disable-bootdelay.patch " builddir="$srcdir/u-boot-v$pkgver" install="$pkgname.post-upgrade" @@ -77,20 +65,8 @@ package() { } sha512sums=" -f97d1531946d749d3a40c4a1c60489382d0100757ac8ed4e3e18b70685ba664641cc56de1e2fef2e00efc78e6779f0f52fab2c1ff98fefac98303973572ffd69 u-boot-v2021.10.tar.gz +7cd524d5c4b692c99d61fae4e7d99287ce4bca06884dc02b62bd69dfdf594cc9232c13c5b8dbb3aeac125bf7907591dbc6a40e2ea3e39f024bd5a5d42aeaa4cd u-boot-v2022.07.tar.gz d6e1ca6100fdc0ecd9559d556bb8f6699ff807a180d097808417cdacc07fc22b58f8bf33f1f104fcbb28201bd873e469f251176605bec123870ff49bde50024c update-u-boot -4d5526a9d492a45213bee5252407061441fc2a760e9ece2651f51a628ab55aac98ce66ff397276b8f5f5bb497ec07ed0344896ae127680666324a4968cd03418 0001-sunxi-DT-H6-update-device-tree-files.patch -edc73a3472f4fb2c02785cb07042d2547fa0cebab4bd27b15085ccdc73aa92597d1325e8f7daed1e5d2a5f0875a763bcdb7ffef6af43612c87bbe37008d6ac3e 0002-tools-mkimage-Add-Allwinner-TOC0-support.patch -8e60a6a633126265e5f9b363144ce77beaa0460856d007570f1772783cd8e47a250441ffeec525c7f9ac030350d52d2248f4bfc0a0e975cdc1d5525b61008002 0003-sunxi-Support-both-SPL-image-types.patch -86b5c6cb43a7bb2dd9a0434c3875114a6ff569d994c23db8da1c149556dc2042d1af7f802dee4873a39dbd2a8059a1d891476c324594c53901de7455b1fc07f3 0004-sunxi-Support-building-a-SPL-as-a-TOC0-image.patch -6addeafd556814239a5b0ac3c7604c84b8598d62e8f9fc71f506fb8d312500328a1bd66a688173ccaa8b197e0eb6d3cf2d31c8a1029033ca9a3204ea2906f17b 0005-sunxi-DT-H6-Add-USB3-to-Pine-H64-DTS.patch -fe38e2cd396a1ba432e2951b35dfed4aa0b481499bd4cbbba5af7111717554fa73d3f0e762be1b060651e4216a7efcd13f12ad56f2026c1dcbf575520a372aab 0006-sunxi-Load-sun8i-secure-monitor-to-SRAM-A2.patch -127b630f1656b7a2ebb946310cf9f478ec07d2df0899635b324efab9b76cf3158bfd01901400542ab2d314e3ac3de1680dc73e03bed7de29628cb4995f97cfd4 0007-pinephone-Add-volume_key-environment-variable.patch -034b3f8800627d9a49761ef663f794375c816b33bf88d83eb9b87a73d123004de2c418a1a02761557463bfd6e311a3b85ea8159eeb13c32882ba99668430e4ab 0008-Enable-led-on-boot-to-notify-user-of-boot-status.patch -ee42dabe8d8dce1200babb5d5060373d80a5457ee06a8adc3b18b0b7f2b8dca183cc5480c2d833ce3df823c3061c6c9f57b8b6a5122cfec0a6d4e24f1033e65c 0009-disable-bootdelay.patch -74747317194f46855bc553c1371a3134db9017041ca3d8afdb377ca1162805931e3c93e44728e6d8980babd5e326f1654b70c683c1ee10dbfe4ddfb88684de6b 0010-Reduce-DRAM-speed-to-528-for-better-compatibility-wi.patch -ae2d0baf7c2048e142230741368db1d0520b1764d62e798098d2548b0ba9622f098f64edc0988db10963543ca0169ae6f3db609f436e1fd090d785274cf30283 0011-mmc-sunxi-Add-support-for-DMA-transfers.patch -eff2901ac5e14949f326a9d8b553f6f32d7e89502929090595b360d1b76d0d3335c94d0c4960b25603f9786524baf2386251bd4a18582ed1012a6db3e5e84618 0012-mmc-sunxi-DDR-DMA-support-for-SPL.patch -f2ee73c774758bd13872d370bc7990474adc453531dacf15664609ca0fdc2a4844d4769376c370b7d18896ac734a7080ee709066659647a4cf0368928bf5e198 0013-spl-ARM-Enable-CPU-caches.patch -86d9587cb2b0ca99fb4090bd0daacd47c0043858654f6f7114c8d0ed6c660eb2b8bc0b37de6723e738df9b1137d62482f00764c284f4aa0a6054db9efe754db9 0014-common-expose-DRAM-clock-speed.patch +86d9587cb2b0ca99fb4090bd0daacd47c0043858654f6f7114c8d0ed6c660eb2b8bc0b37de6723e738df9b1137d62482f00764c284f4aa0a6054db9efe754db9 0001-common-expose-DRAM-clock-speed.patch +9b9a5bd2cb5c04715a5bb2d34bfc06e63817dba7ec40fa2b09000a0827590623e85ed5877d6b6bb39f2bb917e5e9d8e1379e3df9128e3304be06abc487c68df2 0002-disable-bootdelay.patch "