4
0

added support for old raspberry pi

This commit is contained in:
Benjamin Böhmke 2019-11-08 22:33:12 +01:00
parent 9e1a592de4
commit 6679b00bcd
5 changed files with 233 additions and 45 deletions

View File

@ -1,8 +1,10 @@
FROM debian:buster AS uboot
FROM debian:buster AS build_base
RUN apt-get update && \
apt-get install -y build-essential git wget bison flex gcc-arm-linux-gnueabi device-tree-compiler bc
FROM build_base AS uboot
RUN mkdir /uboot_build/ && \
mkdir /uboot/
@ -43,6 +45,12 @@ RUN make CROSS_COMPILE=arm-linux-gnueabi- distclean && \
make CROSS_COMPILE=arm-linux-gnueabi- -j8 u-boot.bin && \
cp u-boot.bin /uboot/u-boot_rpi4.bin
FROM build_base AS uboot_tool
ADD ./resources/uboot.c /uboot.c
RUN arm-linux-gnueabi-gcc -Wall -static -static-libgcc -o /uboot_tool /uboot.c
FROM alpine:3.10
@ -70,5 +78,6 @@ RUN cd /genext2fs && \
ADD ./resources /resources
COPY --from=uboot /uboot/ /uboot/
COPY --from=uboot_tool /uboot_tool /uboot_tool
WORKDIR /work

View File

@ -1,46 +1,106 @@
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# static config
setenv boot_partition_a 2
setenv boot_partition_b 3
setenv boot_limit 2
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
setenv boot_partition_a 0x02
setenv boot_partition_b 0x03
setenv boot_limit 0x02
setenv boot_partition_base "/dev/mmcblk0p"
setenv addr_version 0x10000
setenv addr_boot_counter 0x10001
setenv addr_boot_partition 0x10002
# set default values if env not set
if printenv boot_count; then
else
setenv boot_count 1
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# load persistence values
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# clear memory
mw.b 0x10000 0 0x404
# load uboot file
fatload mmc 0:1 0x10000 uboot.dat 0x400
# check CRC
crc32 0x10000 0x3FC 0x10400
if itest *0x103FC -ne *0x10400; then
echo "invalid CRC -> fallback to default values"
# default values
mw.b ${addr_version} 0x01
mw.b ${addr_boot_counter} 0x00
mw.b ${addr_boot_partition} ${boot_partition_a}
fi
if printenv boot_partition; then
# check if valid partition a or b
if test ${boot_partition} -ne ${boot_partition_a} && test ${boot_partition} -ne ${boot_partition_b}; then
setenv boot_partition ${boot_partition_a}
fi
else
setenv boot_partition ${boot_partition_a}
# ensure boot partition is valid
if itest.b *${addr_boot_partition} -ne ${boot_partition_a} && test.b *${addr_boot_partition} -ne ${boot_partition_b}; then
mw.b ${addr_boot_partition} ${boot_partition_a}
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# fallback boot
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo "Check fallback boot"
# switch boot partition if boot count exceed limit
if test ${boot_count} -ge ${boot_limit}; then
if itest.b *${addr_boot_counter} -ge ${boot_limit}; then
echo "!!! Boot limit exceed !!!"
if test ${boot_partition} -eq ${boot_partition_a}; then
setenv boot_partition ${boot_partition_b}
if itest *${addr_boot_partition} -eq ${boot_partition_a}; then
mv.b ${addr_boot_partition} ${boot_partition_b}
else
setenv boot_partition ${boot_partition_a}
mv.b ${addr_boot_partition} ${boot_partition_a}
fi
setenv boot_count 0
mw.b ${addr_boot_counter} 0
setexpr.b boot_partition *${addr_boot_partition}
echo "Switch active partition to ${boot_partition_base}${boot_partition}"
else
# increase boot_count
setexpr.b tmp *${addr_boot_counter} + 1
mw.b ${addr_boot_counter} ${tmp}
setexpr.b boot_partition *${addr_boot_partition}
fi
# increase boot_count
setexpr boot_count ${boot_count} + 1
# store settings
saveenv
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# store persistence values
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# overwrite version
mw.b 0x10000 0x01
# calculate crc
crc32 0x10000 0x3FC 0x103FC
# save to uboot file
fatwrite mmc 0:1 0x10000 uboot.dat 0x400
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# select kernel
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo "select kernel"
setenv boot_kernel "/boot/uImage"
# only if new pi a new kernel is required
setexpr board_new_pi ${board_revision} \& 0x800000
if test ${board_new_pi} > 0; then
echo "new board"
# get cpu id from revision
setexpr board_cpu ${board_revision} \& 0xF000
# at the moment CPU except the oldest need the new kernel
if test ${board_cpu} > 0x0000; then
setenv boot_kernel "/boot/uImage2"
fi
else
echo "old board"
fi
echo "Load kernel ${boot_kernel}"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# boot
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# load bootargs from pi boot loader
fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs
@ -48,7 +108,7 @@ fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs
setexpr bootargs sub " root=[^ ]+" " root=${boot_partition_base}${boot_partition}" "${bootargs}"
# load kernel and boot
ext4load mmc 0:${boot_partition} ${kernel_addr_r} /boot/uImage
ext4load mmc 0:${boot_partition} ${kernel_addr_r} ${boot_kernel}
bootm ${kernel_addr_r} - ${fdt_addr}
reset
reset

View File

@ -12,8 +12,8 @@ set -e
: ${DEFAULT_ROOT_PASSWORD:="alpine"}
: ${SIZE_BOOT:="100M"}
: ${SIZE_ROOT_FS:="150M"}
: ${SIZE_ROOT_PART:="250M"}
: ${SIZE_ROOT_FS:="200M"}
: ${SIZE_ROOT_PART:="500M"}
: ${SIZE_DATA:="20M"}
: ${IMG_NAME:="alpine-${ALPINE_BRANCH}-sdcard"}
@ -22,7 +22,7 @@ set -e
# static config
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
RES_PATH=/resources/
BASE_PACKAGES="alpine-base tzdata parted ifupdown e2fsprogs-extra util-linux coreutils linux-rpi2 uboot-tools openntpd"
BASE_PACKAGES="alpine-base tzdata parted ifupdown e2fsprogs-extra util-linux coreutils linux-rpi linux-rpi2"
WORK_PATH="/work"
OUTPUT_PATH="/output"
@ -139,20 +139,12 @@ mkdir -p ${ROOTFS_PATH}/dev/shm
mkdir -p ${ROOTFS_PATH}/var/lock
# time
chroot_exec rc-update add openntpd default
cat >${ROOTFS_PATH}/etc/conf.d/openntpd <<EOF
NTPD_OPTS="-s"
EOF
cat >${ROOTFS_PATH}/etc/ntpd.conf <<EOF
servers pool.ntp.org
EOF
chroot_exec rc-update add ntpd default
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# uboot tools config
cat >${ROOTFS_PATH}/etc/fw_env.config <<EOF
/uboot/uboot.env 0x0000 0x4000
EOF
# uboot tools
cp /uboot_tool ${ROOTFS_PATH}/sbin/uboot_tool
# TODO REMOVE THIS
# mark system as booted (should be moved to application)
@ -160,7 +152,7 @@ cat >${ROOTFS_PATH}/etc/local.d/99-uboot.start <<EOF
#!/bin/sh
mount -o remount,rw /uboot
fw_setenv boot_count 1
/sbin/uboot_tool reset_counter
sync
mount -o remount,ro /uboot
@ -182,6 +174,9 @@ ln -s /data/etc/dropbear/dropbear.conf ${ROOTFS_PATH}/etc/conf.d/dropbear
# cleanup
rm -rf ${ROOTFS_PATH}/var/cache/apk/*
rm -rf ${ROOTFS_PATH}/boot/initramfs*
rm -rf ${ROOTFS_PATH}/boot/System*
rm -rf ${ROOTFS_PATH}/boot/config*
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Move persistent data to /data"
@ -248,7 +243,8 @@ ln -fs /data/etc/shadow ${ROOTFS_PATH}/etc/shadow
echo ">> Prepare kernel for uboot"
# build uImage
mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n "Linux kernel" -d ${ROOTFS_PATH}/boot/vmlinuz-rpi2 ${ROOTFS_PATH}/boot/uImage
mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n "Linux kernel" -d ${ROOTFS_PATH}/boot/vmlinuz-rpi ${ROOTFS_PATH}/boot/uImage
mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n "Linux kernel" -d ${ROOTFS_PATH}/boot/vmlinuz-rpi2 ${ROOTFS_PATH}/boot/uImage2
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

View File

@ -19,10 +19,8 @@ current_idx=$(rdev | sed 's#/dev/mmcblk0p\([^ ]*\).*#\1#')
if [ $current_idx -eq 2 ]; then
echo "Start update for partition B"
flash_idx=3
else
echo "Start update for partition A"
flash_idx=2
fi
flash_device="/dev/mmcblk0p${flash_idx}"
@ -33,7 +31,7 @@ gunzip -c ${image_file} | dd of=${flash_device} status=progress
# switch active partition
mount -o remount,rw /uboot
fw_setenv boot_partition ${flash_idx}
/sbin/uboot_tool part_switch
sync
mount -o remount,ro /uboot

125
resources/uboot.c Normal file
View File

@ -0,0 +1,125 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
char* uboot_file = "/uboot/uboot.dat";
void printHelp() {
printf("Usage: uboot_tool [COMMAND]\n");
printf("\n");
printf("Commands:\n");
printf(" part_current - show current partition\n");
printf(" part_switch - switch active partition\n");
printf(" reset_counter - reset boot counter\n");
printf(" version - show version of file\n");
}
uint32_t crc32(uint8_t* data, size_t length, uint32_t seed) {
uint32_t crc = ~seed;
while (length--) {
crc ^= (*data++);
for (unsigned int j = 0; j < 8; j++) {
if (crc & 1) {
crc = (crc >> 1) ^ 0xedb88320L;
} else {
crc = crc >> 1;
}
}
}
return ~crc;
}
int main(int argc, char* argv[]) {
// show help if no command given
if (argc < 2) {
printHelp();
return 1;
}
char* cmd = argv[1];
// read uboot file
FILE* file = fopen(uboot_file, "rb");
if (file == NULL) {
printf("Failed to open uboot file: %s\n", uboot_file);
return 2;
}
uint8_t data[1024];
size_t err = fread(data, 1, sizeof(data), file);
if (err == 0) {
printf("Failed to read uboot file: %s\n", uboot_file);
return 2;
}
fclose(file);
// get crc from file
uint32_t crc = (data[1023] << 24) +
(data[1022] << 16) +
(data[1021] << 8) +
data[1020];
// check if CRC is valid
if (crc != crc32(data, 0x3FC, 0)) {
fprintf(stderr, "Invalid CRC -> fallback to default\n");
memset(data, 0, sizeof(data));
// file version
data[0] = 1;
// boot counter
data[1] = 0;
// boot partition
data[2] = 2; // A=2, B=3
}
// handle commands
uint8_t save = 0;
if (strcmp(cmd, "version") == 0) {
printf("0x%02x\n", data[0]);
} else if (strcmp(cmd, "part_current") == 0) {
printf("%d\n", data[2]);
} else if (strcmp(cmd, "part_switch") == 0) {
if (data[2] == 2) {
data[2] = 3;
} else {
data[2] = 2;
}
save = 1;
} else if (strcmp(cmd, "reset_counter") == 0) {
data[1] = 0;
save = 1;
} else {
printf("Unknown command\n");
return 10;
}
if (save == 1) {
// calculate new CRC
crc = crc32(data, 0x3FC, 0);
data[1023] = (uint8_t)((crc & 0xFF000000U)>>24);
data[1022] = (uint8_t)((crc & 0x00FF0000U)>>16);
data[1021] = (uint8_t)((crc & 0x0000FF00U)>>8);
data[1020] = (uint8_t)((crc & 0x000000FFU));
// write uboot file
file = fopen(uboot_file, "wb");
if (file == NULL) {
printf("Failed to open uboot file: %s\n", uboot_file);
return 4;
}
size_t err = fwrite(data, 1, sizeof(data), file);
if (err == 0) {
printf("Failed to write uboot file: %s\n", uboot_file);
return 4;
}
fclose(file);
}
return 0;
}