mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 09:32:34 +00:00
755 lines
25 KiB
Diff
755 lines
25 KiB
Diff
From 86c2de0e5b6b800525df4abf533366c34554064f Mon Sep 17 00:00:00 2001
|
|
From: Daniel Golle <daniel@makrotopia.org>
|
|
Date: Mon, 15 Feb 2021 14:37:17 +0000
|
|
Subject: [PATCH 17/22] image: add support for building FIT image with
|
|
filesystem
|
|
|
|
Allow for single (external-data) FIT image to hold kernel, dtb and
|
|
squashfs. In that way, the bootloader verify the system integrity
|
|
including the rootfs, flashing sysupgrade and factory on many platforms
|
|
becomes much easier.
|
|
In short: mkimage has a parameter '-E' which allows generating FIT
|
|
images with 'external' data rather than embedding the data into the
|
|
device-tree blob itself. In this way, the FIT structure itself remains
|
|
small and can be parsed easily (rather than having to page around
|
|
megabytes of image content). This patch makes use of that and adds
|
|
support for adding sub-images of type 'filesystem' which are used to
|
|
store the squashfs. Now U-Boot can verify the whole OS and the new
|
|
partition parsers added in the Linux kernel can detect the filesystem
|
|
sub-images and create partitions for them, and select the active
|
|
rootfs volume based on the configuration in FIT.
|
|
|
|
This new FIT partition parser works for NOR flash (on top of mtdblock),
|
|
NAND flash (on top of ubiblock) as well as classic block devices
|
|
(ie. eMMC, SDcard, SATA, NVME, ...) as well as .
|
|
See the follow-up commits for a good example of its use (on SPI-NAND).
|
|
|
|
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
---
|
|
include/image-commands.mk | 3 +-
|
|
package/base-files/files/lib/upgrade/nand.sh | 102 +++++---
|
|
scripts/mkits.sh | 45 +++-
|
|
target/linux/generic/config-5.10 | 1 +
|
|
.../generic/files/block/partitions/fit.c | 234 ++++++++++++++++++
|
|
.../400-block-fit-partition-parser.patch | 96 +++++++
|
|
...to-create-ubiblock-device-for-rootfs.patch | 5 +-
|
|
7 files changed, 442 insertions(+), 44 deletions(-)
|
|
create mode 100644 target/linux/generic/files/block/partitions/fit.c
|
|
create mode 100644 target/linux/generic/hack-5.10/400-block-fit-partition-parser.patch
|
|
|
|
diff --git a/include/image-commands.mk b/include/image-commands.mk
|
|
index 51e745958e..bddbed6052 100644
|
|
--- a/include/image-commands.mk
|
|
+++ b/include/image-commands.mk
|
|
@@ -200,11 +200,12 @@ define Build/fit
|
|
$(TOPDIR)/scripts/mkits.sh \
|
|
-D $(DEVICE_NAME) -o $@.its -k $@ \
|
|
$(if $(word 2,$(1)),-d $(word 2,$(1))) -C $(word 1,$(1)) \
|
|
+ $(if $(word 3,$(1)),-r $(IMAGE_ROOTFS) -f $(subst _,$(comma),$(DEVICE_NAME))) \
|
|
-a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \
|
|
$(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \
|
|
-c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config@1") \
|
|
-A $(LINUX_KARCH) -v $(LINUX_VERSION)
|
|
- PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new
|
|
+ PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage $(if $(word 3,$(1)),-E -B 0x1000 -p 0x1000) -f $@.its $@.new
|
|
@mv $@.new $@
|
|
endef
|
|
|
|
diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh
|
|
index e6f58df4f5..5bc9ff83f9 100644
|
|
--- a/package/base-files/files/lib/upgrade/nand.sh
|
|
+++ b/package/base-files/files/lib/upgrade/nand.sh
|
|
@@ -3,13 +3,13 @@
|
|
|
|
. /lib/functions.sh
|
|
|
|
-# 'kernel' partition on NAND contains the kernel
|
|
+# 'kernel' partition or UBI volume on NAND contains the kernel
|
|
CI_KERNPART="${CI_KERNPART:-kernel}"
|
|
|
|
# 'ubi' partition on NAND contains UBI
|
|
CI_UBIPART="${CI_UBIPART:-ubi}"
|
|
|
|
-# 'rootfs' partition on NAND contains the rootfs
|
|
+# 'rootfs' UBI volume on NAND contains the rootfs
|
|
CI_ROOTPART="${CI_ROOTPART:-rootfs}"
|
|
|
|
ubi_mknod() {
|
|
@@ -117,9 +117,11 @@ nand_restore_config() {
|
|
nand_upgrade_prepare_ubi() {
|
|
local rootfs_length="$1"
|
|
local rootfs_type="$2"
|
|
- local has_kernel="${3:-0}"
|
|
+ local kernel_length="$3"
|
|
local has_env="${4:-0}"
|
|
|
|
+ [ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1
|
|
+
|
|
local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
|
|
if [ ! "$mtdnum" ]; then
|
|
echo "cannot find ubi mtd partition $CI_UBIPART"
|
|
@@ -148,23 +150,24 @@ nand_upgrade_prepare_ubi() {
|
|
local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
|
|
local data_ubivol="$( nand_find_volume $ubidev rootfs_data )"
|
|
|
|
- # remove ubiblock device of rootfs
|
|
- local root_ubiblk="ubiblock${root_ubivol:3}"
|
|
- if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then
|
|
- echo "removing $root_ubiblk"
|
|
- if ! ubiblock -r /dev/$root_ubivol; then
|
|
- echo "cannot remove $root_ubiblk"
|
|
- return 1;
|
|
+ local ubiblk ubiblkvol
|
|
+ for ubiblk in /dev/ubiblock*_? ; do
|
|
+ [ -e "$ubiblk" ] || continue
|
|
+ echo "removing ubiblock${ubiblk:13}"
|
|
+ ubiblkvol=ubi${ubiblk:13}
|
|
+ if ! ubiblock -r /dev/$ubiblkvol; then
|
|
+ echo "cannot remove $ubiblk"
|
|
+ return 1
|
|
fi
|
|
- fi
|
|
+ done
|
|
|
|
# kill volumes
|
|
[ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || true
|
|
- [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_ROOTPART || true
|
|
+ [ "$root_ubivol" -a "$root_ubivol" != "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_ROOTPART || true
|
|
[ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true
|
|
|
|
# update kernel
|
|
- if [ "$has_kernel" = "1" ]; then
|
|
+ if [ -n "$kernel_length" ]; then
|
|
if ! ubimkvol /dev/$ubidev -N $CI_KERNPART -s $kernel_length; then
|
|
echo "cannot create kernel volume"
|
|
return 1;
|
|
@@ -172,15 +175,17 @@ nand_upgrade_prepare_ubi() {
|
|
fi
|
|
|
|
# update rootfs
|
|
- local root_size_param
|
|
- if [ "$rootfs_type" = "ubifs" ]; then
|
|
- root_size_param="-m"
|
|
- else
|
|
- root_size_param="-s $rootfs_length"
|
|
- fi
|
|
- if ! ubimkvol /dev/$ubidev -N $CI_ROOTPART $root_size_param; then
|
|
- echo "cannot create rootfs volume"
|
|
- return 1;
|
|
+ if [ -n "$rootfs_length" ]; then
|
|
+ local root_size_param
|
|
+ if [ "$rootfs_type" = "ubifs" ]; then
|
|
+ root_size_param="-m"
|
|
+ else
|
|
+ root_size_param="-s $rootfs_length"
|
|
+ fi
|
|
+ if ! ubimkvol /dev/$ubidev -N $CI_ROOTPART $rootfs_size_param; then
|
|
+ echo "cannot create rootfs volume"
|
|
+ return 1;
|
|
+ fi
|
|
fi
|
|
|
|
# create rootfs_data for non-ubifs rootfs
|
|
@@ -232,7 +237,7 @@ nand_upgrade_ubinized() {
|
|
nand_upgrade_ubifs() {
|
|
local rootfs_length=$( (cat $1 | wc -c) 2> /dev/null)
|
|
|
|
- nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0"
|
|
+ nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "" ""
|
|
|
|
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
|
local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
|
|
@@ -241,39 +246,59 @@ nand_upgrade_ubifs() {
|
|
nand_do_upgrade_success
|
|
}
|
|
|
|
+nand_upgrade_fit() {
|
|
+ local fit_file="$1"
|
|
+ local fit_length="$(wc -c < "$fit_file")"
|
|
+
|
|
+ nand_upgrade_prepare_ubi "" "" "$fit_length" "1"
|
|
+
|
|
+ local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")"
|
|
+ local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")"
|
|
+ ubiupdatevol /dev/$fit_ubivol -s $fit_length $fit_file
|
|
+
|
|
+ nand_do_upgrade_success
|
|
+}
|
|
+
|
|
nand_upgrade_tar() {
|
|
local tar_file="$1"
|
|
local kernel_mtd="$(find_mtd_index $CI_KERNPART)"
|
|
|
|
- local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
|
|
+ local board_dir=$(tar tf "$tar_file" | grep -m 1 '^sysupgrade-.*/$')
|
|
board_dir=${board_dir%/}
|
|
|
|
- local kernel_length=$( (tar xf $tar_file ${board_dir}/kernel -O | wc -c) 2> /dev/null)
|
|
- local rootfs_length=$( (tar xf $tar_file ${board_dir}/root -O | wc -c) 2> /dev/null)
|
|
+ kernel_length=$( (tar xf "$tar_file" ${board_dir}/kernel -O | wc -c) 2> /dev/null)
|
|
+ local has_rootfs=0
|
|
+ local rootfs_length
|
|
+ local rootfs_type
|
|
|
|
- local rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)"
|
|
+ tar tf "$tar_file" ${board_dir}/root 1>/dev/null 2>/dev/null && has_rootfs=1
|
|
+ [ "$has_rootfs" = "1" ] && {
|
|
+ rootfs_length=$( (tar xf "$tar_file" ${board_dir}/root -O | wc -c) 2> /dev/null)
|
|
+ rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)"
|
|
+ }
|
|
|
|
local has_kernel=1
|
|
local has_env=0
|
|
|
|
[ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && {
|
|
- tar xf $tar_file ${board_dir}/kernel -O | mtd write - $CI_KERNPART
|
|
+ tar xf "$tar_file" ${board_dir}/kernel -O | mtd write - $CI_KERNPART
|
|
}
|
|
- [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0
|
|
+ [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=
|
|
|
|
- nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$has_kernel" "$has_env"
|
|
+ nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "${has_kernel:+$kernel_length}" "$has_env"
|
|
|
|
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
|
[ "$has_kernel" = "1" ] && {
|
|
- local kern_ubivol="$(nand_find_volume $ubidev $CI_KERNPART)"
|
|
- tar xf $tar_file ${board_dir}/kernel -O | \
|
|
+ local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )"
|
|
+ tar xf "$tar_file" ${board_dir}/kernel -O | \
|
|
ubiupdatevol /dev/$kern_ubivol -s $kernel_length -
|
|
}
|
|
|
|
- local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
|
|
- tar xf $tar_file ${board_dir}/root -O | \
|
|
- ubiupdatevol /dev/$root_ubivol -s $rootfs_length -
|
|
-
|
|
+ [ "$has_rootfs" = "1" ] && {
|
|
+ local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
|
|
+ tar xf "$tar_file" ${board_dir}/root -O | \
|
|
+ ubiupdatevol /dev/$root_ubivol -s $rootfs_length -
|
|
+ }
|
|
nand_do_upgrade_success
|
|
}
|
|
|
|
@@ -281,9 +306,10 @@ nand_upgrade_tar() {
|
|
nand_do_upgrade() {
|
|
local file_type=$(identify $1)
|
|
|
|
- [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs"
|
|
+ [ ! "$( find_mtd_index "$CI_UBIPART" )" ] && CI_UBIPART="rootfs"
|
|
|
|
case "$file_type" in
|
|
+ "fit") nand_upgrade_fit $1;;
|
|
"ubi") nand_upgrade_ubinized $1;;
|
|
"ubifs") nand_upgrade_ubifs $1;;
|
|
*) nand_upgrade_tar $1;;
|
|
@@ -309,7 +335,7 @@ nand_do_platform_check() {
|
|
local control_length=$( (tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null)
|
|
local file_type="$(identify $2)"
|
|
|
|
- [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ] && {
|
|
+ [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" -a "$file_type" != "fit" ] && {
|
|
echo "Invalid sysupgrade file."
|
|
return 1
|
|
}
|
|
diff --git a/scripts/mkits.sh b/scripts/mkits.sh
|
|
index bb629d6fca..3d68fdacbc 100755
|
|
--- a/scripts/mkits.sh
|
|
+++ b/scripts/mkits.sh
|
|
@@ -23,18 +23,23 @@ usage() {
|
|
printf "\n\t-c ==> set config name 'config'"
|
|
printf "\n\t-a ==> set load address to 'addr' (hex)"
|
|
printf "\n\t-e ==> set entry point to 'entry' (hex)"
|
|
+ printf "\n\t-f ==> set device tree compatible string"
|
|
printf "\n\t-v ==> set kernel version to 'version'"
|
|
printf "\n\t-k ==> include kernel image 'kernel'"
|
|
printf "\n\t-D ==> human friendly Device Tree Blob 'name'"
|
|
printf "\n\t-n ==> fdt unit-address 'address'"
|
|
printf "\n\t-d ==> include Device Tree Blob 'dtb'"
|
|
+ printf "\n\t-r ==> include RootFS blob"
|
|
+ printf "\n\t-H ==> specify hash algo instead of SHA1"
|
|
printf "\n\t-o ==> create output file 'its_file'\n"
|
|
exit 1
|
|
}
|
|
|
|
FDTNUM=1
|
|
+ROOTFSNUM=1
|
|
+HASH=sha1
|
|
|
|
-while getopts ":A:a:c:C:D:d:e:k:n:o:v:" OPTION
|
|
+while getopts ":A:a:c:C:D:d:e:f:k:n:o:v:r:S" OPTION
|
|
do
|
|
case $OPTION in
|
|
A ) ARCH=$OPTARG;;
|
|
@@ -44,9 +49,12 @@ do
|
|
D ) DEVICE=$OPTARG;;
|
|
d ) DTB=$OPTARG;;
|
|
e ) ENTRY_ADDR=$OPTARG;;
|
|
+ f ) COMPATIBLE=$OPTARG;;
|
|
k ) KERNEL=$OPTARG;;
|
|
n ) FDTNUM=$OPTARG;;
|
|
o ) OUTPUT=$OPTARG;;
|
|
+ r ) ROOTFS=$OPTARG;;
|
|
+ S ) HASH=$OPTARG;;
|
|
v ) VERSION=$OPTARG;;
|
|
* ) echo "Invalid option passed to '$0' (options:$*)"
|
|
usage;;
|
|
@@ -62,11 +70,16 @@ fi
|
|
|
|
ARCH_UPPER=$(echo "$ARCH" | tr '[:lower:]' '[:upper:]')
|
|
|
|
+if [ -n "${COMPATIBLE}" ]; then
|
|
+ COMPATIBLE_PROP="compatible = \"${COMPATIBLE}\";"
|
|
+fi
|
|
+
|
|
# Conditionally create fdt information
|
|
if [ -n "${DTB}" ]; then
|
|
FDT_NODE="
|
|
fdt@$FDTNUM {
|
|
description = \"${ARCH_UPPER} OpenWrt ${DEVICE} device tree blob\";
|
|
+ ${COMPATIBLE_PROP}
|
|
data = /incbin/(\"${DTB}\");
|
|
type = \"flat_dt\";
|
|
arch = \"${ARCH}\";
|
|
@@ -75,13 +88,34 @@ if [ -n "${DTB}" ]; then
|
|
algo = \"crc32\";
|
|
};
|
|
hash@2 {
|
|
- algo = \"sha1\";
|
|
+ algo = \"${HASH}\";
|
|
};
|
|
};
|
|
"
|
|
FDT_PROP="fdt = \"fdt@$FDTNUM\";"
|
|
fi
|
|
|
|
+if [ -n "${ROOTFS}" ]; then
|
|
+ dd if="${ROOTFS}" of="${ROOTFS}.pagesync" bs=4096 conv=sync
|
|
+ ROOTFS_NODE="
|
|
+ rootfs@$ROOTFSNUM {
|
|
+ description = \"${ARCH_UPPER} OpenWrt ${DEVICE} rootfs\";
|
|
+ ${COMPATIBLE_PROP}
|
|
+ data = /incbin/(\"${ROOTFS}.pagesync\");
|
|
+ type = \"filesystem\";
|
|
+ arch = \"${ARCH}\";
|
|
+ compression = \"none\";
|
|
+ hash@1 {
|
|
+ algo = \"crc32\";
|
|
+ };
|
|
+ hash@2 {
|
|
+ algo = \"${HASH}\";
|
|
+ };
|
|
+ };
|
|
+"
|
|
+ ROOTFS_PROP="loadables = \"rootfs@${ROOTFSNUM}\";"
|
|
+fi
|
|
+
|
|
# Create a default, fully populated DTS file
|
|
DATA="/dts-v1/;
|
|
|
|
@@ -103,18 +137,21 @@ DATA="/dts-v1/;
|
|
algo = \"crc32\";
|
|
};
|
|
hash@2 {
|
|
- algo = \"sha1\";
|
|
+ algo = \"$HASH\";
|
|
};
|
|
};
|
|
${FDT_NODE}
|
|
+${ROOTFS_NODE}
|
|
};
|
|
|
|
configurations {
|
|
default = \"${CONFIG}\";
|
|
${CONFIG} {
|
|
- description = \"OpenWrt\";
|
|
+ description = \"OpenWrt ${DEVICE}\";
|
|
kernel = \"kernel@1\";
|
|
${FDT_PROP}
|
|
+ ${ROOTFS_PROP}
|
|
+ ${COMPATIBLE_PROP}
|
|
};
|
|
};
|
|
};"
|
|
diff --git a/target/linux/generic/config-5.10 b/target/linux/generic/config-5.10
|
|
index f7cc6c8561..ba6317e35f 100644
|
|
--- a/target/linux/generic/config-5.10
|
|
+++ b/target/linux/generic/config-5.10
|
|
@@ -1859,6 +1859,7 @@ CONFIG_FIB_RULES=y
|
|
# CONFIG_FIELDBUS_DEV is not set
|
|
CONFIG_FILE_LOCKING=y
|
|
# CONFIG_FIND_BIT_BENCHMARK is not set
|
|
+# CONFIG_FIT_PARTITION is not set
|
|
# CONFIG_FIREWIRE is not set
|
|
# CONFIG_FIREWIRE_NOSY is not set
|
|
# CONFIG_FIREWIRE_SERIAL is not set
|
|
diff --git a/target/linux/generic/files/block/partitions/fit.c b/target/linux/generic/files/block/partitions/fit.c
|
|
new file mode 100644
|
|
index 0000000000..3694a22667
|
|
--- /dev/null
|
|
+++ b/target/linux/generic/files/block/partitions/fit.c
|
|
@@ -0,0 +1,234 @@
|
|
+// SPvDX-License-Identifier: GPL-2.0
|
|
+/*
|
|
+ * fs/partitions/fit.c
|
|
+ * Copyright (C) 2021 Daniel Golle
|
|
+ *
|
|
+ * headers extracted from U-Boot mkimage sources
|
|
+ * (C) Copyright 2008 Semihalf
|
|
+ * (C) Copyright 2000-2005
|
|
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
|
+ *
|
|
+ * based on existing partition parsers
|
|
+ * Copyright (C) 1991-1998 Linus Torvalds
|
|
+ * Re-organised Feb 1998 Russell King
|
|
+ */
|
|
+
|
|
+#define pr_fmt(fmt) fmt
|
|
+
|
|
+#include <linux/types.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/of_device.h>
|
|
+#include <linux/of_fdt.h>
|
|
+#include <linux/libfdt.h>
|
|
+
|
|
+#include "check.h"
|
|
+
|
|
+#define FIT_IMAGES_PATH "/images"
|
|
+#define FIT_CONFS_PATH "/configurations"
|
|
+
|
|
+/* hash/signature/key node */
|
|
+#define FIT_HASH_NODENAME "hash"
|
|
+#define FIT_ALGO_PROP "algo"
|
|
+#define FIT_VALUE_PROP "value"
|
|
+#define FIT_IGNORE_PROP "uboot-ignore"
|
|
+#define FIT_SIG_NODENAME "signature"
|
|
+#define FIT_KEY_REQUIRED "required"
|
|
+#define FIT_KEY_HINT "key-name-hint"
|
|
+
|
|
+/* cipher node */
|
|
+#define FIT_CIPHER_NODENAME "cipher"
|
|
+#define FIT_ALGO_PROP "algo"
|
|
+
|
|
+/* image node */
|
|
+#define FIT_DATA_PROP "data"
|
|
+#define FIT_DATA_POSITION_PROP "data-position"
|
|
+#define FIT_DATA_OFFSET_PROP "data-offset"
|
|
+#define FIT_DATA_SIZE_PROP "data-size"
|
|
+#define FIT_TIMESTAMP_PROP "timestamp"
|
|
+#define FIT_DESC_PROP "description"
|
|
+#define FIT_ARCH_PROP "arch"
|
|
+#define FIT_TYPE_PROP "type"
|
|
+#define FIT_OS_PROP "os"
|
|
+#define FIT_COMP_PROP "compression"
|
|
+#define FIT_ENTRY_PROP "entry"
|
|
+#define FIT_LOAD_PROP "load"
|
|
+
|
|
+/* configuration node */
|
|
+#define FIT_KERNEL_PROP "kernel"
|
|
+#define FIT_FILESYSTEM_PROP "filesystem"
|
|
+#define FIT_RAMDISK_PROP "ramdisk"
|
|
+#define FIT_FDT_PROP "fdt"
|
|
+#define FIT_LOADABLE_PROP "loadables"
|
|
+#define FIT_DEFAULT_PROP "default"
|
|
+#define FIT_SETUP_PROP "setup"
|
|
+#define FIT_FPGA_PROP "fpga"
|
|
+#define FIT_FIRMWARE_PROP "firmware"
|
|
+#define FIT_STANDALONE_PROP "standalone"
|
|
+
|
|
+#define FIT_MAX_HASH_LEN HASH_MAX_DIGEST_SIZE
|
|
+
|
|
+int fit_partition(struct parsed_partitions *state)
|
|
+{
|
|
+ struct address_space *mapping = state->bdev->bd_inode->i_mapping;
|
|
+ struct page *page = read_mapping_page(mapping, 0, NULL);
|
|
+ void *fit, *init_fit;
|
|
+ struct partition_meta_info *info;
|
|
+ char tmp[sizeof(info->volname)];
|
|
+ u64 dsize, dsectors, isectors;
|
|
+ u32 size, image_pos, image_len;
|
|
+ const u32 *image_offset_be, *image_len_be, *image_pos_be;
|
|
+ int ret = 1, node, images, config, slot;
|
|
+ const char *image_name, *image_type, *image_description, *config_default,
|
|
+ *config_description, *config_loadables;
|
|
+ int image_name_len, image_type_len, image_description_len, config_default_len,
|
|
+ config_description_len, config_loadables_len;
|
|
+ sector_t start_sect, nr_sects;
|
|
+ size_t label_min;
|
|
+
|
|
+ if (!page)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ init_fit = page_address(page);
|
|
+
|
|
+ if (!init_fit) {
|
|
+ put_page(page);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (fdt_check_header(init_fit)) {
|
|
+ put_page(page);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ dsectors = get_capacity(state->bdev->bd_disk);
|
|
+ dsize = dsectors << SECTOR_SHIFT;
|
|
+
|
|
+ printk(KERN_INFO "FIT: volume size: %llu sectors (%llu bytes)\n", dsectors, dsize);
|
|
+
|
|
+ size = fdt_totalsize(init_fit);
|
|
+ isectors = size >> SECTOR_SHIFT;
|
|
+ if ((isectors << SECTOR_SHIFT) < size)
|
|
+ ++isectors;
|
|
+
|
|
+ printk(KERN_INFO "FIT: FDT structure size: %llu sectors (%u bytes)\n", isectors, size);
|
|
+
|
|
+ if (size >= dsize || size > PAGE_SIZE)
|
|
+ {
|
|
+ put_page(page);
|
|
+ state->access_beyond_eod = (size >= dsize);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ fit = kmemdup(init_fit, size, GFP_KERNEL);
|
|
+ put_page(page);
|
|
+ if (!fit)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ config = fdt_path_offset(fit, FIT_CONFS_PATH);
|
|
+ if (config < 0) {
|
|
+ printk(KERN_INFO "FIT: Cannot find %s node: %d\n", FIT_CONFS_PATH, images);
|
|
+ ret = -ENOENT;
|
|
+ goto ret_out;
|
|
+ }
|
|
+
|
|
+ config_default = fdt_getprop(fit, config, FIT_DEFAULT_PROP, &config_default_len);
|
|
+
|
|
+ if (!config_default) {
|
|
+ printk(KERN_INFO "FIT: Cannot find default configuration\n");
|
|
+ ret = -ENOENT;
|
|
+ goto ret_out;
|
|
+ }
|
|
+
|
|
+ node = fdt_subnode_offset(fit, config, config_default);
|
|
+ if (node < 0) {
|
|
+ printk(KERN_INFO "FIT: Cannot find %s node: %d\n", config_default, node);
|
|
+ ret = -ENOENT;
|
|
+ goto ret_out;
|
|
+ }
|
|
+
|
|
+ config_description = fdt_getprop(fit, node, FIT_DESC_PROP, &config_description_len);
|
|
+ config_loadables = fdt_getprop(fit, node, FIT_LOADABLE_PROP, &config_loadables_len);
|
|
+
|
|
+ printk(KERN_INFO "FIT: Default configuration: %s%s%s%s\n", config_default,
|
|
+ config_description?" (":"", config_description?:"", config_description?")":"");
|
|
+
|
|
+ images = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
|
+ if (images < 0) {
|
|
+ printk(KERN_INFO "FIT: Cannot find %s node: %d\n", FIT_IMAGES_PATH, images);
|
|
+ ret = -EINVAL;
|
|
+ goto ret_out;
|
|
+ }
|
|
+
|
|
+ slot = 1;
|
|
+ fdt_for_each_subnode(node, fit, images) {
|
|
+ image_name = fdt_get_name(fit, node, &image_name_len);
|
|
+ image_type = fdt_getprop(fit, node, FIT_TYPE_PROP, &image_type_len);
|
|
+ image_offset_be = fdt_getprop(fit, node, FIT_DATA_OFFSET_PROP, NULL);
|
|
+ image_pos_be = fdt_getprop(fit, node, FIT_DATA_POSITION_PROP, NULL);
|
|
+ image_len_be = fdt_getprop(fit, node, FIT_DATA_SIZE_PROP, NULL);
|
|
+ if (!image_name || !image_type || !image_len_be)
|
|
+ continue;
|
|
+
|
|
+ image_len = be32_to_cpu(*image_len_be);
|
|
+ if (!image_len)
|
|
+ continue;
|
|
+
|
|
+ if (image_offset_be)
|
|
+ image_pos = be32_to_cpu(*image_offset_be) + size;
|
|
+ else if (image_pos_be)
|
|
+ image_pos = be32_to_cpu(*image_pos_be);
|
|
+ else
|
|
+ continue;
|
|
+
|
|
+ image_description = fdt_getprop(fit, node, FIT_DESC_PROP, &image_description_len);
|
|
+
|
|
+ printk(KERN_INFO "FIT: %16s sub-image 0x%08x - 0x%08x '%s' %s%s%s\n",
|
|
+ image_type, image_pos, image_pos + image_len, image_name,
|
|
+ image_description?"(":"", image_description?:"", image_description?") ":"");
|
|
+
|
|
+ if (strcmp(image_type, FIT_FILESYSTEM_PROP))
|
|
+ continue;
|
|
+
|
|
+ if (image_pos & ((1 << PAGE_SHIFT)-1)) {
|
|
+ printk(KERN_INFO "FIT: image %s start not aligned to page boundaries, skipping\n", image_name);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (image_len & ((1 << PAGE_SHIFT)-1)) {
|
|
+ printk(KERN_INFO "FIT: sub-image %s end not aligned to page boundaries, skipping\n", image_name);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ start_sect = image_pos >> SECTOR_SHIFT;
|
|
+ nr_sects = image_len >> SECTOR_SHIFT;
|
|
+
|
|
+ if (start_sect + nr_sects > dsectors) {
|
|
+ state->access_beyond_eod = 1;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ put_partition(state, slot, start_sect, nr_sects);
|
|
+ state->parts[slot].flags = 0;
|
|
+ info = &state->parts[slot].info;
|
|
+
|
|
+ label_min = min_t(int, sizeof(info->volname) - 1, image_name_len);
|
|
+ strncpy(info->volname, image_name, label_min);
|
|
+ info->volname[label_min] = '\0';
|
|
+
|
|
+ snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
|
|
+ strlcat(state->pp_buf, tmp, PAGE_SIZE);
|
|
+
|
|
+ state->parts[slot].has_info = true;
|
|
+
|
|
+ if (config_loadables && !strcmp(image_name, config_loadables)) {
|
|
+ printk(KERN_INFO "FIT: selecting configured loadable %s to be root filesystem\n", image_name);
|
|
+ state->parts[slot].flags |= ADDPART_FLAG_ROOTDEV;
|
|
+ }
|
|
+
|
|
+ ++slot;
|
|
+ }
|
|
+
|
|
+ret_out:
|
|
+ kfree(fit);
|
|
+ return ret;
|
|
+}
|
|
diff --git a/target/linux/generic/hack-5.10/400-block-fit-partition-parser.patch b/target/linux/generic/hack-5.10/400-block-fit-partition-parser.patch
|
|
new file mode 100644
|
|
index 0000000000..9eaf8637d0
|
|
--- /dev/null
|
|
+++ b/target/linux/generic/hack-5.10/400-block-fit-partition-parser.patch
|
|
@@ -0,0 +1,96 @@
|
|
+--- a/block/blk.h
|
|
++++ b/block/blk.h
|
|
+@@ -357,6 +357,7 @@ char *disk_name(struct gendisk *hd, int
|
|
+ #define ADDPART_FLAG_NONE 0
|
|
+ #define ADDPART_FLAG_RAID 1
|
|
+ #define ADDPART_FLAG_WHOLEDISK 2
|
|
++#define ADDPART_FLAG_ROOTDEV 4
|
|
+ void delete_partition(struct hd_struct *part);
|
|
+ int bdev_add_partition(struct block_device *bdev, int partno,
|
|
+ sector_t start, sector_t length);
|
|
+--- a/block/partitions/Kconfig
|
|
++++ b/block/partitions/Kconfig
|
|
+@@ -101,6 +101,13 @@ config ATARI_PARTITION
|
|
+ Say Y here if you would like to use hard disks under Linux which
|
|
+ were partitioned under the Atari OS.
|
|
+
|
|
++config FIT_PARTITION
|
|
++ bool "Flattened-Image-Tree (FIT) partition support" if PARTITION_ADVANCED
|
|
++ default n
|
|
++ help
|
|
++ Say Y here if your system needs to mount the filesystem part of
|
|
++ a Flattened-Image-Tree (FIT) image commonly used with Das U-Boot.
|
|
++
|
|
+ config IBM_PARTITION
|
|
+ bool "IBM disk label and partition support"
|
|
+ depends on PARTITION_ADVANCED && S390
|
|
+--- a/block/partitions/Makefile
|
|
++++ b/block/partitions/Makefile
|
|
+@@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o
|
|
+ obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
|
|
+ obj-$(CONFIG_ATARI_PARTITION) += atari.o
|
|
+ obj-$(CONFIG_AIX_PARTITION) += aix.o
|
|
++obj-$(CONFIG_FIT_PARTITION) += fit.o
|
|
+ obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o
|
|
+ obj-$(CONFIG_MAC_PARTITION) += mac.o
|
|
+ obj-$(CONFIG_LDM_PARTITION) += ldm.o
|
|
+--- a/block/partitions/check.h
|
|
++++ b/block/partitions/check.h
|
|
+@@ -58,6 +58,7 @@ int amiga_partition(struct parsed_partit
|
|
+ int atari_partition(struct parsed_partitions *state);
|
|
+ int cmdline_partition(struct parsed_partitions *state);
|
|
+ int efi_partition(struct parsed_partitions *state);
|
|
++int fit_partition(struct parsed_partitions *state);
|
|
+ int ibm_partition(struct parsed_partitions *);
|
|
+ int karma_partition(struct parsed_partitions *state);
|
|
+ int ldm_partition(struct parsed_partitions *state);
|
|
+--- a/block/partitions/core.c
|
|
++++ b/block/partitions/core.c
|
|
+@@ -10,6 +10,8 @@
|
|
+ #include <linux/vmalloc.h>
|
|
+ #include <linux/blktrace_api.h>
|
|
+ #include <linux/raid/detect.h>
|
|
++#include <linux/root_dev.h>
|
|
++
|
|
+ #include "check.h"
|
|
+
|
|
+ static int (*check_part[])(struct parsed_partitions *) = {
|
|
+@@ -46,6 +48,9 @@ static int (*check_part[])(struct parsed
|
|
+ #ifdef CONFIG_EFI_PARTITION
|
|
+ efi_partition, /* this must come before msdos */
|
|
+ #endif
|
|
++#ifdef CONFIG_FIT_PARTITION
|
|
++ fit_partition,
|
|
++#endif
|
|
+ #ifdef CONFIG_SGI_PARTITION
|
|
+ sgi_partition,
|
|
+ #endif
|
|
+@@ -694,6 +699,9 @@ static bool blk_add_partition(struct gen
|
|
+ (state->parts[p].flags & ADDPART_FLAG_RAID))
|
|
+ md_autodetect_dev(part_to_dev(part)->devt);
|
|
+
|
|
++ if ((state->parts[p].flags & ADDPART_FLAG_ROOTDEV) && ROOT_DEV == 0)
|
|
++ ROOT_DEV = part_to_dev(part)->devt;
|
|
++
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+--- a/drivers/mtd/ubi/block.c
|
|
++++ b/drivers/mtd/ubi/block.c
|
|
+@@ -396,7 +396,7 @@ int ubiblock_create(struct ubi_volume_in
|
|
+ dev->leb_size = vi->usable_leb_size;
|
|
+
|
|
+ /* Initialize the gendisk of this ubiblock device */
|
|
+- gd = alloc_disk(1);
|
|
++ gd = alloc_disk(0);
|
|
+ if (!gd) {
|
|
+ pr_err("UBI: block: alloc_disk failed\n");
|
|
+ ret = -ENODEV;
|
|
+@@ -413,6 +413,7 @@ int ubiblock_create(struct ubi_volume_in
|
|
+ goto out_put_disk;
|
|
+ }
|
|
+ gd->private_data = dev;
|
|
++ gd->flags |= GENHD_FL_EXT_DEVT;
|
|
+ sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
|
|
+ set_capacity(gd, disk_capacity);
|
|
+ dev->gd = gd;
|
|
diff --git a/target/linux/generic/pending-5.10/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/target/linux/generic/pending-5.10/491-ubi-auto-create-ubiblock-device-for-rootfs.patch
|
|
index e5ee2c8656..a2b48fd4fc 100644
|
|
--- a/target/linux/generic/pending-5.10/491-ubi-auto-create-ubiblock-device-for-rootfs.patch
|
|
+++ b/target/linux/generic/pending-5.10/491-ubi-auto-create-ubiblock-device-for-rootfs.patch
|
|
@@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
|
|
--- a/drivers/mtd/ubi/block.c
|
|
+++ b/drivers/mtd/ubi/block.c
|
|
-@@ -652,6 +652,44 @@ static void __init ubiblock_create_from_
|
|
+@@ -652,6 +652,47 @@ static void __init ubiblock_create_from_
|
|
}
|
|
}
|
|
|
|
@@ -33,6 +33,9 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
+ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) {
|
|
+ desc = ubi_open_volume_nm(ubi_num, "rootfs", UBI_READONLY);
|
|
+ if (IS_ERR(desc))
|
|
++ desc = ubi_open_volume_nm(ubi_num, "fit", UBI_READONLY);;
|
|
++
|
|
++ if (IS_ERR(desc))
|
|
+ continue;
|
|
+
|
|
+ ubi_get_volume_info(desc, &vi);
|
|
--
|
|
2.25.1
|
|
|