epfl-archive/cs309-psoc/lab_3_1/create_linux_system.sh

515 lines
18 KiB
Bash
Raw Normal View History

2022-04-07 18:54:11 +02:00
#!/bin/bash -x
# ===================================================================================
# usage: create_linux_system.sh [sdcard_device]
#
# positional arguments:
# sdcard_device path to sdcard device file [ex: "/dev/sdb", "/dev/mmcblk0"]
# ===================================================================================
# make sure to be in the same directory as this script
script_dir_abs=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
cd "${script_dir_abs}"
# constants ####################################################################
quartus_dir="$(readlink -m "hw/quartus")"
quartus_project_name="$(basename "$(find "${quartus_dir}" -name "*.qpf")" .qpf)"
quartus_sof_file="$(readlink -m "${quartus_dir}/output_files/${quartus_project_name}.sof")"
fpga_device_part_number="5CSEMA4U23C6" # 5CSEMA5F31C6
preloader_dir="$(readlink -m "sw/hps/preloader")"
preloader_settings_dir="$(readlink -m "${quartus_dir}/hps_isw_handoff/soc_system_hps_0")"
preloader_settings_file="$(readlink -m "${preloader_dir}/settings.bsp")"
preloader_source_tgz_file="$(readlink -m "${SOCEDS_DEST_ROOT}/host_tools/altera/preloader/uboot-socfpga.tar.gz")"
preloader_bin_file="${preloader_dir}/preloader-mkpimage.bin"
uboot_src_dir="$(readlink -m "sw/hps/u-boot")"
uboot_src_git_repo="git://git.denx.de/u-boot.git"
uboot_src_git_checkout_commit="b104b3dc1dd90cdbf67ccf3c51b06e4f1592fe91"
uboot_src_make_config_file="socfpga_de0_nano_soc_defconfig" # socfpga_cyclone5_config
uboot_src_config_file="${uboot_src_dir}/include/configs/socfpga_de0_nano_soc.h" # socfpga_cyclone5_socdk.h
uboot_script_file="$(readlink -m "${uboot_src_dir}/u-boot.script")"
uboot_img_file="$(readlink -m "${uboot_src_dir}/u-boot.img")"
linux_dir="$(readlink -m "sw/hps/linux")"
linux_src_git_repo="https://github.com/altera-opensource/linux-socfpga.git"
linux_src_dir="$(readlink -m "${linux_dir}/source")"
linux_src_git_checkout_commit="9735a22799b9214d17d3c231fe377fc852f042e9"
linux_src_make_config_file="socfpga_defconfig"
linux_kernel_mem_arg="1024M"
linux_zImage_file="$(readlink -m "${linux_src_dir}/arch/arm/boot/zImage")"
linux_dtb_file="$(readlink -m "${linux_src_dir}/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dtb")" # socfpga_cyclone5_socdk.dtb
rootfs_dir="${linux_dir}/rootfs"
rootfs_chroot_dir="$(readlink -m ${rootfs_dir}/ubuntu-core-rootfs)"
rootfs_src_tgz_link="http://cdimage.ubuntu.com/ubuntu-base/releases/14.04.5/release/ubuntu-base-14.04.5-base-armhf.tar.gz"
rootfs_src_tgz_file="$(readlink -m "${rootfs_dir}/${rootfs_src_tgz_link##*/}")"
rootfs_system_config_script_file="${rootfs_dir}/config_system.sh"
rootfs_post_install_config_script_file="${rootfs_dir}/config_post_install.sh"
sdcard_fat32_dir="$(readlink -m "sdcard/fat32")"
sdcard_fat32_rbf_file="$(readlink -m "${sdcard_fat32_dir}/socfpga.rbf")"
sdcard_fat32_uboot_img_file="$(readlink -m "${sdcard_fat32_dir}/$(basename "${uboot_img_file}")")"
sdcard_fat32_uboot_scr_file="$(readlink -m "${sdcard_fat32_dir}/u-boot.scr")"
sdcard_fat32_zImage_file="$(readlink -m "${sdcard_fat32_dir}/zImage")"
sdcard_fat32_dtb_file="$(readlink -m "${sdcard_fat32_dir}/socfpga.dtb")"
sdcard_dev="$(readlink -m "${1}")"
sdcard_ext3_rootfs_tgz_file="$(readlink -m "sdcard/ext3_rootfs.tar.gz")"
sdcard_a2_dir="$(readlink -m "sdcard/a2")"
sdcard_a2_preloader_bin_file="$(readlink -m "${sdcard_a2_dir}/$(basename "${preloader_bin_file}")")"
sdcard_partition_size_fat32="32M"
sdcard_partition_size_linux="512M"
sdcard_partition_number_fat32="1"
sdcard_partition_number_ext3="2"
sdcard_partition_number_a2="3"
if [ "$(echo "${sdcard_dev}" | grep -P "/dev/sd\w.*$")" ]; then
sdcard_dev_fat32_id="${sdcard_partition_number_fat32}"
sdcard_dev_ext3_id="${sdcard_partition_number_ext3}"
sdcard_dev_a2_id="${sdcard_partition_number_a2}"
elif [ "$(echo "${sdcard_dev}" | grep -P "/dev/mmcblk\w.*$")" ]; then
sdcard_dev_fat32_id="p${sdcard_partition_number_fat32}"
sdcard_dev_ext3_id="p${sdcard_partition_number_ext3}"
sdcard_dev_a2_id="p${sdcard_partition_number_a2}"
fi
sdcard_dev_fat32="${sdcard_dev}${sdcard_dev_fat32_id}"
sdcard_dev_ext3="${sdcard_dev}${sdcard_dev_ext3_id}"
sdcard_dev_a2="${sdcard_dev}${sdcard_dev_a2_id}"
sdcard_dev_fat32_mount_point="$(readlink -m "sdcard/mount_point_fat32")"
sdcard_dev_ext3_mount_point="$(readlink -m "sdcard/mount_point_ext3")"
# compile_quartus_project() ####################################################
compile_quartus_project() {
# change working directory to quartus directory
pushd "${quartus_dir}"
# delete old artifacts
rm -rf "c5_pin_model_dump.txt" \
"db/" \
"hps_isw_handoff/" \
"hps_sdram_p0_all_pins.txt" \
"incremental_db/" \
"output_files/" \
"soc_system.sopcinfo" \
"soc_system/" \
"${quartus_project_name}.qws" \
"${sdcard_fat32_rbf_file}"
qsys-generate "soc_system.qsys" --synthesis=VHDL --output-directory="soc_system/" --part="${fpga_device_part_number}"
# Analysis and synthesis
quartus_map "${quartus_project_name}"
# Execute HPS DDR3 pin assignment TCL script
# it is normal for the following script to report an error, but it was
# sucessfully executed
#ddr3_pin_assignment_script="$(find . -name "hps_sdram_p0_pin_assignments.tcl")"
#quartus_sta -t "${ddr3_pin_assignment_script}" "${quartus_project_name}"
# Fitter
quartus_fit "${quartus_project_name}"
# Assembler
quartus_asm "${quartus_project_name}"
#ddr3_pin_assignment_script="$(find . -name "hps_sdram_p0_pin_assignments.tcl")"
#quartus_sta -t "${ddr3_pin_assignment_script}" "${quartus_project_name}"
quartus_sta "${quartus_project_name}"
# convert .sof to .rbf in associated sdcard directory
quartus_cpf -c "${quartus_sof_file}" "${sdcard_fat32_rbf_file}"
# change working directory back to script directory
popd
}
# compile_preloader() ##########################################################
compile_preloader() {
# delete old artifacts
rm -rf "${preloader_dir}" \
"${sdcard_a2_preloader_bin_file}"
# create directory for preloader
mkdir -p "${preloader_dir}"
# change working directory to preloader directory
pushd "${preloader_dir}"
# create bsp settings file
bsp-create-settings \
--bsp-dir "${preloader_dir}" \
--preloader-settings-dir "${preloader_settings_dir}" \
--settings "${preloader_settings_file}" \
--type spl \
--set spl.CROSS_COMPILE "arm-altera-eabi-" \
--set spl.PRELOADER_TGZ "${preloader_source_tgz_file}" \
--set spl.boot.BOOTROM_HANDSHAKE_CFGIO "1" \
--set spl.boot.BOOT_FROM_NAND "0" \
--set spl.boot.BOOT_FROM_QSPI "0" \
--set spl.boot.BOOT_FROM_RAM "0" \
--set spl.boot.BOOT_FROM_SDMMC "1" \
--set spl.boot.CHECKSUM_NEXT_IMAGE "1" \
--set spl.boot.EXE_ON_FPGA "0" \
--set spl.boot.FAT_BOOT_PARTITION "1" \
--set spl.boot.FAT_LOAD_PAYLOAD_NAME "$(basename "${uboot_img_file}")" \
--set spl.boot.FAT_SUPPORT "1" \
--set spl.boot.FPGA_DATA_BASE "0xffff0000" \
--set spl.boot.FPGA_DATA_MAX_SIZE "0x10000" \
--set spl.boot.FPGA_MAX_SIZE "0x10000" \
--set spl.boot.NAND_NEXT_BOOT_IMAGE "0xc0000" \
--set spl.boot.QSPI_NEXT_BOOT_IMAGE "0x60000" \
--set spl.boot.RAMBOOT_PLLRESET "1" \
--set spl.boot.SDMMC_NEXT_BOOT_IMAGE "0x40000" \
--set spl.boot.SDRAM_SCRUBBING "0" \
--set spl.boot.SDRAM_SCRUB_BOOT_REGION_END "0x2000000" \
--set spl.boot.SDRAM_SCRUB_BOOT_REGION_START "0x1000000" \
--set spl.boot.SDRAM_SCRUB_REMAIN_REGION "1" \
--set spl.boot.STATE_REG_ENABLE "1" \
--set spl.boot.WARMRST_SKIP_CFGIO "1" \
--set spl.boot.WATCHDOG_ENABLE "1" \
--set spl.debug.DEBUG_MEMORY_ADDR "0xfffffd00" \
--set spl.debug.DEBUG_MEMORY_SIZE "0x200" \
--set spl.debug.DEBUG_MEMORY_WRITE "0" \
--set spl.debug.HARDWARE_DIAGNOSTIC "0" \
--set spl.debug.SEMIHOSTING "0" \
--set spl.debug.SKIP_SDRAM "0" \
--set spl.performance.SERIAL_SUPPORT "1" \
--set spl.reset_assert.DMA "0" \
--set spl.reset_assert.GPIO0 "0" \
--set spl.reset_assert.GPIO1 "0" \
--set spl.reset_assert.GPIO2 "0" \
--set spl.reset_assert.L4WD1 "0" \
--set spl.reset_assert.OSC1TIMER1 "0" \
--set spl.reset_assert.SDR "0" \
--set spl.reset_assert.SPTIMER0 "0" \
--set spl.reset_assert.SPTIMER1 "0" \
--set spl.warm_reset_handshake.ETR "1" \
--set spl.warm_reset_handshake.FPGA "1" \
--set spl.warm_reset_handshake.SDRAM "0"
# generate bsp
bsp-generate-files \
--bsp-dir "${preloader_dir}" \
--settings "${preloader_settings_file}"
# compile preloader
make -j4
# copy artifacts to associated sdcard directory
cp "${preloader_bin_file}" "${sdcard_a2_preloader_bin_file}"
# change working directory back to script directory
popd
}
# compile_uboot ################################################################
compile_uboot() {
# delete old artifacts
rm -rf "${sdcard_fat32_uboot_scr_file}" \
"${sdcard_fat32_uboot_img_file}"
# if uboot source tree doesn't exist, then download it
if [ ! -d "${uboot_src_dir}" ]; then
git clone "${uboot_src_git_repo}" "${uboot_src_dir}"
fi
# change working directory to uboot source tree directory
pushd "${uboot_src_dir}"
# use cross compiler instead of standard x86 version of gcc
export CROSS_COMPILE=arm-linux-gnueabihf-
# clean up source tree
make distclean
# checkout the following commit (tested and working):
git checkout "${uboot_src_git_checkout_commit}"
# configure uboot for socfpga_cyclone5 architecture
make "${uboot_src_make_config_file}"
## patch the uboot configuration file that describes environment variables
# replace value of CONFIG_BOOTCOMMAND macro (we will always use a script for configuring everything)
# result:
# #define CONFIG_BOOTCOMMAND "run callscript"
perl -pi -e 's/^(#define\s+CONFIG_BOOTCOMMAND)(.*)/$1\t"run callscript"/g' "${uboot_src_config_file}"
# replace value of CONFIG_EXTRA_ENV_SETTINGS macro
# result:
# #define CONFIG_EXTRA_ENV_SETTINGS \
# "scriptfile=u-boot.scr" "\0" \
# "fpgadata=0x2000000" "\0" \
# "callscript=fatload mmc 0:1 $fpgadata $scriptfile;" \
# "source $fpgadata" "\0"
perl -pi -e 'BEGIN{undef $/;} s/^(#define\s+CONFIG_EXTRA_ENV_SETTINGS)(.*)#include/$1\t"scriptfile=u-boot.scr\\0" "fpgadata=0x2000000\\0" "callscript=fatload mmc 0:1 \$fpgadata \$scriptfile; source \$fpgadata\\0"\n\n#include/smg' "${uboot_src_config_file}"
# compile uboot
make -j4
# create uboot script
cat <<EOF > "${uboot_script_file}"
################################################################################
echo --- Resetting Env variables ---
# reset environment variables to default
env default -a
echo --- Setting Env variables ---
# Set the kernel image
setenv bootimage $(basename ${sdcard_fat32_zImage_file});
# address to which the device tree will be loaded
setenv fdtaddr 0x00000100
# Set the devicetree image
setenv fdtimage $(basename ${sdcard_fat32_dtb_file});
# set kernel boot arguments, then boot the kernel
setenv mmcboot 'setenv bootargs mem=${linux_kernel_mem_arg} console=ttyS0,115200 root=\${mmcroot} rw rootwait; \
bootz \${loadaddr} - \${fdtaddr}';
# load linux kernel image and device tree to memory
setenv mmcload 'mmc rescan; \
\${mmcloadcmd} mmc 0:\${mmcloadpart} \${loadaddr} \${bootimage}; \
\${mmcloadcmd} mmc 0:\${mmcloadpart} \${fdtaddr} \${fdtimage}'
# command to be executed to read from sdcard
setenv mmcloadcmd fatload
# sdcard fat32 partition number
setenv mmcloadpart ${sdcard_partition_number_fat32}
# sdcard ext3 identifier
setenv mmcroot /dev/mmcblk0p${sdcard_partition_number_ext3}
# standard input/output
setenv stderr serial
setenv stdin serial
setenv stdout serial
# save environment to sdcard (not needed, but useful to avoid CRC errors on a new sdcard)
saveenv
################################################################################
echo --- Programming FPGA ---
# load rbf from FAT partition into memory
fatload mmc 0:1 \${fpgadata} $(basename ${sdcard_fat32_rbf_file});
# program FPGA
fpga load 0 \${fpgadata} \${filesize};
# enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges
bridge enable;
################################################################################
echo --- Booting Linux ---
# load linux kernel image and device tree to memory
run mmcload;
# set kernel boot arguments, then boot the kernel
run mmcboot;
EOF
# compile uboot script to binary form
mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "${quartus_project_name}" -d "${uboot_script_file}" "${sdcard_fat32_uboot_scr_file}"
# copy artifacts to associated sdcard directory
cp "${uboot_img_file}" "${sdcard_fat32_uboot_img_file}"
# change working directory back to script directory
popd
}
# compile_linux() ##############################################################
compile_linux() {
# if linux source tree doesn't exist, then download it
if [ ! -d "${linux_src_dir}" ]; then
git clone "${linux_src_git_repo}" "${linux_src_dir}"
fi
# change working directory to linux source tree directory
pushd "${linux_src_dir}"
# compile for the ARM architecture
export ARCH=arm
# use cross compiler instead of standard x86 version of gcc
export CROSS_COMPILE=arm-linux-gnueabihf-
# clean up source tree
make distclean
# checkout the following commit (tested and working):
git checkout "${linux_src_git_checkout_commit}"
# configure kernel for socfpga architecture
make "${linux_src_make_config_file}"
# compile zImage
make -j4 zImage
# compile device tree
make -j4 "$(basename "${linux_dtb_file}")"
# copy artifacts to associated sdcard directory
cp "${linux_zImage_file}" "${sdcard_fat32_zImage_file}"
cp "${linux_dtb_file}" "${sdcard_fat32_dtb_file}"
# change working directory back to script directory
popd
}
# create_rootfs() ##############################################################
create_rootfs() {
# if rootfs tarball doesn't exist, then download it
if [ ! -f "${rootfs_src_tgz_file}" ]; then
wget "${rootfs_src_tgz_link}" -O "${rootfs_src_tgz_file}"
fi
# delete old artifacts
sudo rm -rf "${rootfs_chroot_dir}" \
"${sdcard_ext3_rootfs_tgz_file}"
# create dir to extract rootfs
mkdir -p "${rootfs_chroot_dir}"
# extract ubuntu core rootfs
pushd "${rootfs_chroot_dir}"
sudo tar -xzpf "${rootfs_src_tgz_file}"
popd
# copy chroot SYSTEM configuration script to chroot directory
sudo cp "${rootfs_system_config_script_file}" "${rootfs_chroot_dir}"
# edit chroot environment's /etc/rc.local to execute the rootfs
# configuration script
sudo tee "${rootfs_chroot_dir}/etc/rc.local" > "/dev/null" <<EOF
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
/$(basename ${rootfs_system_config_script_file})
exit 0
EOF
# copy chroot POST-INSTALL configuration script to chroot directory
sudo cp "${rootfs_post_install_config_script_file}" "${rootfs_chroot_dir}"
# create archive of updated rootfs
pushd "${rootfs_chroot_dir}"
sudo tar -czpf "${sdcard_ext3_rootfs_tgz_file}" .
popd
}
# partition_sdcard() ###########################################################
partition_sdcard() {
# manually partitioning the sdcard
# sudo fdisk /dev/sdx
# use the following commands
# n p 3 <default> 4095 t a2 (2048 is default first sector)
# n p 1 <default> +32M t 1 b (4096 is default first sector)
# n p 2 <default> +512M t 2 83 (69632 is default first sector)
# w
# result
# Device Boot Start End Sectors Size Id Type
# /dev/sdb1 4096 69631 65536 32M b W95 FAT32
# /dev/sdb2 69632 1118207 1048576 512M 83 Linux
# /dev/sdb3 2048 4095 2048 1M a2 unknown
# note that you can choose any size for the FAT32 and Linux partitions,
# but the a2 partition must be 1M.
# automatically partitioning the sdcard
# wipe partition table
sudo dd if="/dev/zero" of="${sdcard_dev}" bs=512 count=1
# create partitions
# no need to specify the partition number for the first invocation of
# the "t" command in fdisk, because there is only 1 partition at this
# point
echo -e "n\np\n3\n\n4095\nt\na2\nn\np\n1\n\n+${sdcard_partition_size_fat32}\nt\n1\nb\nn\np\n2\n\n+${sdcard_partition_size_linux}\nt\n2\n83\nw\nq\n" | sudo fdisk "${sdcard_dev}"
# create filesystems
sudo mkfs.vfat "${sdcard_dev_fat32}"
sudo mkfs.ext3 -F "${sdcard_dev_ext3}"
}
# write_sdcard() ###############################################################
write_sdcard() {
# create mount point for sdcard
mkdir -p "${sdcard_dev_fat32_mount_point}"
mkdir -p "${sdcard_dev_ext3_mount_point}"
# mount sdcard partitions
sudo mount "${sdcard_dev_fat32}" "${sdcard_dev_fat32_mount_point}"
sudo mount "${sdcard_dev_ext3}" "${sdcard_dev_ext3_mount_point}"
# preloader
sudo dd if="${sdcard_a2_preloader_bin_file}" of="${sdcard_dev_a2}" bs=64K seek=0
# fpga .rbf, uboot .img, uboot .scr, linux zImage, linux .dtb
sudo cp "${sdcard_fat32_dir}"/* "${sdcard_dev_fat32_mount_point}"
# linux rootfs
pushd "${sdcard_dev_ext3_mount_point}"
sudo tar -xzf "${sdcard_ext3_rootfs_tgz_file}"
popd
# flush write buffers to target
sudo sync
# unmount sdcard partitions
sudo umount "${sdcard_dev_fat32_mount_point}"
sudo umount "${sdcard_dev_ext3_mount_point}"
# delete mount points for sdcard
rm -rf "${sdcard_dev_fat32_mount_point}"
rm -rf "${sdcard_dev_ext3_mount_point}"
}
# Script execution #############################################################
# Report script line number on any error (non-zero exit code).
trap 'echo "Error on line ${LINENO}" 1>&2' ERR
set -e
# Create sdcard output directories
mkdir -p "${sdcard_a2_dir}"
mkdir -p "${sdcard_fat32_dir}"
compile_quartus_project
compile_preloader
compile_uboot
compile_linux
create_rootfs
# Write sdcard if it exists
if [ -z "${sdcard_dev}" ]; then
echo "sdcard argument not provided => no sdcard written."
elif [ -b "${sdcard_dev}" ]; then
partition_sdcard
write_sdcard
fi
# Make sure MSEL = 000000