diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..13d072e3e43d8a8d51f4790464b35e391c321c5d --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/firmware +/firmware-nonfree +/bluez-firmware +/raspberrypi-kernel +/log +/repo +/output* +/root +/boot +/rootfs* +/img diff --git a/README.en.md b/README.en.md index 696ca58aa936a7b623b3244ac004a7a17caa8562..626faa16a300fc66ff0e503aeecfe1a50042506c 100644 --- a/README.en.md +++ b/README.en.md @@ -1,36 +1,53 @@ # raspberrypi #### Description -It provides scripts for building openEuler image on Raspberry Pi and documents -#### Software Architecture -Software architecture description +This repository provides scripts for building openEuler image for Raspberry Pi and related documents: -#### Installation +* [Script for building openEuler image for Raspberry Pi](build_img.sh) +* [Building openEuler image for Raspberry Pi](documents/openEuler镜像的构建.md) +* [Install openEuler on a SD card](documents/树莓派刷机.md) +* [How to use Raspberry Pi](documents/树莓派使用.md) -1. xxxx -2. xxxx -3. xxxx -#### Instructions +#### Build openEuler image -1. xxxx -2. xxxx -3. xxxx +##### Prepare the environment -#### Contribution +To build openEuler ARM64 image for Raspberry Pi, the requirements of runing scripts of this repository are as follows: +- OS: openEuler or Centos 7/8 +- Architecture: ARM -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request +For example, you can use [QEMU](https://www.qemu.org/) to build ARM system emulation or directly use an ARM hardware such as Raspberry Pi. +##### Run the scripts to build image -#### Gitee Feature +Refer to [Script for building openEuler image for Raspberry Pi](documents/openEuler镜像的构建.md) for details. -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +Build script: build_img.sh,which can be set 0/5/7 parameters. + +1. Build with default parameters + +`sudo bash build_img.sh` + +2. Build with custom parameters + +`sudo bash build_img.sh KERNEL_URL KERNEL_BRANCH KERNEL_DEFCONFIG DEFAULT_DEFCONFIG REPO_FILE_URL --cores MAKE_CORES` + +or + +`sudo bash build_img.sh KERNEL_URL KERNEL_BRANCH KERNEL_DEFCONFIG DEFAULT_DEFCONFIG REPO_FILE_URL` + +The meaning of each parameter: + +- KERNEL_URL:The URL of kernel source's repository,which defaults to `git@gitee.com:openeuler/raspberrypi-kernel.git`. +- KERNEL_BRANCH:The branch name of kernel source's repository,which defaults to `openEuler-1.0-LTS-raspi`. +- KERNEL_DEFCONFIG:The filename of configuration for compiling kernel, which defaults to `openeuler-raspi_defconfig`. The configuration file should be in the config directory or in arch/arm64/configs of the kernel source. If this configuration file does not exist, the script uses the next parameter: DEFAULT_DEFCONFIG. +- DEFAULT_DEFCONFIG:The filename of configuration for kernel, which defaults to `openeuler-raspi_defconfig`. The configuration file should be in arch/arm64/configs of the kernel source. If both KERNEL_DEFCONFIG and this file do not exist, the process of building image will exit. +- REPO_FILE:The URL or name of openEuler's file, which defaults to `openEuler-1.0-LTS.repo`. Caution, if REPO_FILE is a file name, please make sure this file in the config directory. Otherwise, if REPO_FILE is a URL, please make sure you can get a correct repo file from this URL. +- --cores:Followed by parameter MAKE_CORES +- MAKE_CORES:The number of parallel compilations, according to the actual number of CPU of the server running the script. The default is 18. + +#### Use image + +Refer to [Install openEuler on a SD card](documents/树莓派刷机.md) and [How to use Raspberry Pi](documents/树莓派使用.md) for details about how to use the image on Raspberry Pi. \ No newline at end of file diff --git a/README.md b/README.md index a7b46398f4dc04e1ed20b25837af80e6bf653206..bc1f66a02f39bea1459e40cf887effceb5be3039 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,54 @@ # raspberrypi #### 介绍 -It provides scripts for building openEuler image on Raspberry Pi and documents -#### 软件架构 -软件架构说明 +本仓库提供适用于树莓派的openEuler镜像的构建脚本和相关文档: +* [适用于树莓派的openEuler镜像构建脚本](build_img.sh) +* [openEuler镜像的构建](documents/openEuler镜像的构建.md) +* [树莓派刷机](documents/树莓派刷机.md) +* [树莓派使用](documents/树莓派使用.md) -#### 安装教程 +#### openEuler镜像构建 -1. xxxx -2. xxxx -3. xxxx +##### 准备环境 -#### 使用说明 +用于生成 openEuler ARM64 的树莓派镜像。 -1. xxxx -2. xxxx -3. xxxx +本仓库的脚本运行环境要求: +- 操作系统:openEuler 或 Centos 7/8 +- 架构:ARM -#### 参与贡献 +可以使用 [QEMU](https://www.qemu.org/) 模拟器搭建 ARM 运行环境或者直接使用 ARM 架构的主机(例如,树莓派)。 -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request +##### 构建镜像 +详细过程参见 [openEuler镜像的构建](documents/openEuler镜像的构建.md)。 -#### 码云特技 +构建脚本 build_img.sh,其后可设置0/5/7个参数。 -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 -5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +1. 使用脚本默认参数构建 + +`sudo bash build_img.sh` + +2. 自行设置参数构建 + +`sudo bash build_img.sh --cores ` + +或 + +`sudo bash build_img.sh ` + +其中,各个参数意义: + +- KERNEL_URL:内核源码的项目地址,默认为`git@gitee.com:openeuler/raspberrypi-kernel.git`。 +- KERNEL_BRANCH:内核源码的对应分支,默认为`openEuler-1.0-LTS-raspi`。 +- KERNEL_DEFCONFIG:内核编译使用的配置文件名称,默认为`openeuler-raspi_defconfig`,在本目录的 config 目录下或内核源码的目录 arch/arm64/configs 下。如果该文件不存在则使用配置文件 DEFAULT_DEFCONFIG。 +- DEFAULT_DEFCONFIG:内核默认配置文件名称,默认为`openeuler-raspi_defconfig`,在内核源码的目录 arch/arm64/configs 下。如果 KERNEL_DEFCONFIG 和该文件均不存在则退出镜像构建过程。 +- REPO_FILE:openEuler 开发源的 repo 文件的 URL 或者文件名称, 默认为`openEuler-1.0-LTS.repo`。注意,如果 REPO_FILE 为文件名称,需要保证该文件在脚本 build_img.sh 所在目录的 config 文件夹下。 +- --cores:其后跟参数 MAKE_CORES。 +- MAKE_CORES:并行编译的数量,根据运行脚本的服务器CPU实际数目设定,默认为18。 + +#### 镜像使用 + +镜像刷写 SD 卡并使用树莓派,详见 [树莓派刷机](documents/树莓派刷机.md) 和 [树莓派使用](documents/树莓派使用.md)。 \ No newline at end of file diff --git a/build_img.sh b/build_img.sh new file mode 100644 index 0000000000000000000000000000000000000000..adaa37dcdb232361360a2371e513e9a186669918 --- /dev/null +++ b/build_img.sh @@ -0,0 +1,465 @@ +#!/bin/bash +set -e + +if [[ $# -ne 0 && $# -ne 5 && $# -ne 7 ]]; then + echo "params length: $# is not 0/5/7." + exit 1 +fi +cur_dir=`pwd` +run_dir=${cur_dir} +kernel_url="git@gitee.com:openeuler/raspberrypi-kernel.git" +kernel_branch="openEuler-1.0-LTS-rasp" +kernel_defconfig="openeuler-raspi_defconfig" +default_defconfig="openeuler-raspi_defconfig" +repo_file=openEuler-1.0-LTS.repo + +date_str=$(date "+%Y%m%d") +output_dir=${run_dir}/output +rootfs_dir=${run_dir}/rootfs_${date_str} +root_mnt=${run_dir}/root +boot_mnt=${run_dir}/boot +make_cores=18 +if [[ $# -eq 5 || $# -eq 7 ]]; then + if [[ $1 != "" ]]; then + kernel_url=$1 + fi + if [[ $2 != "" ]]; then + kernel_branch=$2 + fi + if [[ $3 != "" ]]; then + kernel_defconfig=$3 + fi + if [[ $4 != "" ]]; then + default_defconfig=$4 + fi + if [[ $5 != "" ]]; then + repo_file=$5 + fi +fi +if [[ $# -eq 7 && $6 == "--cores" && $7 -ne 0 ]]; then + make_cores=$7 +fi +kernel_name=${kernel_url##*/} +kernel_name=${kernel_name%.*} +repo_file_name=${repo_file##*/} +img_suffix=${repo_file_name%%-*} +img_suffix=`echo $img_suffix | grep -Eo "^[a-zA-Z ]*"` +os_release_name=${img_suffix}-release +img_file=${run_dir}/img/${date_str}/${img_suffix}_${date_str}.img + +ERROR(){ + echo `date` - ERROR, $* | tee -a ${cur_dir}/log/log_${date_str}.log +} + +LOG(){ + echo `date` - INFO, $* | tee -a ${cur_dir}/log/log_${date_str}.log +} + +prepare(){ + LOG "prepare begin..." + rmp_names=("bison" "flex" "parted" "wget" "multipath-tools") + rmp_install_names=("bison" "flex" "parted" "wget" "kpartx") + rmp_len=${#rmp_names[@]} + for (( i=0; i<${rmp_len}; i++ )) + do + rpm -qa | grep ${rmp_names[i]} &> /dev/null + [ $? -eq 0 ] || yum install -y ${rmp_install_names[i]} &> /dev/null + [ $? -ne 0 ] && echo "yum install ${rmp_install_names[i]} failed." && ERROR "yum install ${rmp_install_names[i]} failed." && yum_right=3 + done + [ $yum_right ] && exit 3 + if [ ! -d ${cur_dir}/log ]; then + mkdir ${cur_dir}/log + fi + if [ ! -d ${run_dir}/img ]; then + mkdir ${run_dir}/img + fi + if [ -d ${cur_dir}/repo ]; then + rm -rf ${cur_dir}/repo + fi + mkdir ${cur_dir}/repo + if [ "${repo_file:0:4}" = "http" ]; then + # rpm_url=`wget -q -O - ${repo_file} | grep "^baseurl=" | cut -d '=' -f 2 | xargs` + wget ${repo_file} -P ${cur_dir}/repo/ + else + # rpm_url=`cat ${repo_file} | grep "^baseurl=" | grep "everything" | cut -d '=' -f 2 | xargs` + cp ${cur_dir}/config/${repo_file} ${cur_dir}/repo/${repo_file_name} + fi + if [ $? -ne 0 ]; then + ERROR ${repo_file} not found. + exit 1 + else + yumdownloader --downloaddir=${cur_dir}/repo/ $os_release_name -c ${cur_dir}/repo/${repo_file_name} + os_release_name=`ls -r ${cur_dir}/repo/${os_release_name}*.rpm | head -n 1` + if [ -z "${os_release_name}" ]; then + ERROR "Fail to download ${os_release_name}!" + exit 1 + fi + fi + if [ ! -d ${run_dir}/img/${date_str} ]; then + mkdir -p ${run_dir}/img/${date_str} + fi + LOG "prepare end." +} + +update_firmware(){ + LOG "update firmware begin..." + cd "${run_dir}" + ######## firmware + if [[ ! -d firmware ]]; then + git clone --depth=1 https://github.com/raspberrypi/firmware + if [[ $? -eq 0 ]]; then + LOG "clone firmware done." + else + ERROR "clone firmware failed." + exit 1 + fi + else + cd firmware + git pull origin master + cd ../ + fi + ######## bluez-firmware + if [[ ! -d bluez-firmware ]]; then + git clone --depth=1 https://github.com/RPi-Distro/bluez-firmware + if [[ $? -eq 0 ]]; then + LOG "clone bluez-firmware done." + else + ERROR "clone bluez-firmware failed." + exit 1 + fi + else + cd bluez-firmware + git pull origin master + cd ../ + fi + ######## firmware-nonfree + if [[ ! -d firmware-nonfree ]]; then + git clone --depth=1 https://github.com/RPi-Distro/firmware-nonfree + if [[ $? -eq 0 ]]; then + LOG "clone firmware-nonfree done." + else + ERROR "clone firmware-nonfree failed." + exit 1 + fi + else + cd firmware-nonfree + git pull origin master + cd ../ + fi + LOG "update firmware end." +} + +make_kernel(){ + LOG "make kernel begin..." + kernel_dir_tmp=$1 + cd "${kernel_dir_tmp}" + if [[ ${kernel_defconfig} != "" ]]; then + if [[ -f ${cur_dir}/config/${kernel_defconfig} ]]; then + cur_config=${cur_dir}/config/${kernel_defconfig} + elif [[ -f arch/arm64/configs/${kernel_defconfig} ]]; then + cur_config=arch/arm64/configs/${kernel_defconfig} + else + ERROR "kernel config: ${kernel_defconfig} not found." + exit 1 + fi + elif [[ -f arch/arm64/configs/${default_defconfig} ]]; then + cur_config=arch/arm64/configs/${default_defconfig} + kernel_defconfig=${default_defconfig} + else + ERROR "kernel config: ${default_defconfig} not found." + exit 1 + fi + # make ARCH=arm64 ${kernel_defconfig} + # if [[ $? -eq 0 ]]; then + # #### + # else + # ERROR "make ARCH=arm64 ${kernel_defconfig} failed!" + # exit 1 + # fi + kernel_commitid=$(git rev-parse HEAD) + output_dir=${output_dir}/${kernel_commitid} + if [ -f ${output_dir}/.${kernel_defconfig}.DONE ] ; then + echo This kernel has already been built successfully before. Use the last built kernel image. + return 0 + fi + find ${output_dir}/ -mindepth 1 -maxdepth 1 -print0 | xargs -0 rm -rf + make distclean + cp ${cur_config} .config + make ARCH=arm64 -j${make_cores} + if [[ $? -eq 0 ]]; then + mkdir -p ${output_dir} + make ARCH=arm64 INSTALL_MOD_PATH=${output_dir}/ modules_install + if [[ $? -eq 0 ]]; then + cp arch/arm64/boot/Image ${output_dir}/ + cp arch/arm64/boot/dts/broadcom/*.dtb ${output_dir}/ + mkdir ${output_dir}/overlays + cp arch/arm64/boot/dts/overlays/*.dtb* ${output_dir}/overlays/ + LOG "kernel content in ${output_dir}." + else + ERROR "modules install failed!" + exit 1 + fi + else + ERROR "make ARCH=arm64 -j${make_cores} failed!" + exit 1 + fi + touch ${output_dir}/.${kernel_defconfig}.DONE + LOG "make kernel end." +} + +update_kernel(){ + LOG "update kernel begin..." + cd "${run_dir}" + kernel_dir="" + for file in `ls` + do + if [[ ${file} = ${kernel_name} && -d ${file}/.git ]]; then + kernel_dir=${run_dir}/${file} + break + fi + done + + if [[ ${kernel_dir} = "" ]]; then + git clone ${kernel_url} + if [[ $? -eq 0 ]]; then + LOG "clone ${kernel_name} done." + else + ERROR "clone ${kernel_name} failed." + exit 1 + fi + kernel_dir=${run_dir}/${kernel_name} + else + cd "${kernel_name}" + remote_url_exist=`git remote -v | grep "origin"` + remote_url=`git ls-remote --get-url origin` + if [[ ${remote_url_exist} = "" || ${remote_url} != ${kernel_url} ]]; then + cd ../ + rm -rf ${kernel_name} + git clone ${kernel_url} + if [[ $? -eq 0 ]]; then + LOG "clone ${kernel_name} done." + else + ERROR "clone ${kernel_name} failed." + exit 1 + fi + fi + fi + cd "${kernel_dir}" + cur_branch=`git branch | grep \*` + cur_branch=${cur_branch##*\ } + exist_branch=0 + if [[ ${cur_branch} = ${kernel_branch} ]]; then + exist_branch=1 + else + for branch in `git branch -a` + do + branch=${branch##*\ } + if [[ ${branch} = ${kernel_branch} ]]; then + exist_branch=1 + git checkout ${kernel_branch} + break + fi + done + if [[ ${exist_branch} -eq 0 ]]; then + git fetch origin + for branch in `git branch -a` + do + branch=${branch##*\ } + if [[ ${branch} = "remotes/origin/${kernel_branch}" ]]; then + git checkout remotes/origin/${kernel_branch} + # git config --global user.name "yafen" + # git config --global user.email "yafen@iscas.ac.cn" + git checkout -b ${kernel_branch} + LOG "git checkout -b ${kernel_branch} done." + exist_branch=1 + break + fi + done + fi + fi + if [[ ${exist_branch} -eq 0 ]]; then + ERROR "no ${kernel_branch} found." + exit 1 + else + git pull origin ${kernel_branch} # git_rst=`xxx` + make_kernel ${kernel_dir} + fi + # if [[ ${git_rst} = Already* ]]; then + # echo "updated." + # if [ ! -d ${run_dir}/output ]; then + # make_kernel ${kernel_dir} + # else + # output_dir=${run_dir}/output + # fi + # elif [[ ${git_rst} = fatal* ]]; then + # echo "get newest kernel failed!!!" + # ERROR "get newest kernel failed!!!" + # exit 1 + # else + # cd "${kernel_dir}" + # make_kernel ${kernel_dir} + # fi + LOG "update kernel end." +} + +make_rootfs(){ + LOG "make rootfs for ${repo_file} begin..." + cd "${run_dir}" + if [[ -d ${rootfs_dir} ]]; then + if [[ -d ${rootfs_dir}/dev && `ls ${rootfs_dir}/dev | wc -l` -gt 1 ]]; then + umount -l ${rootfs_dir}/dev + fi + if [[ -d ${rootfs_dir}/proc && `ls ${rootfs_dir}/proc | wc -l` -gt 0 ]]; then + umount -l ${rootfs_dir}/proc + fi + if [[ -d ${rootfs_dir}/sys && `ls ${rootfs_dir}/sys | wc -l` -gt 0 ]]; then + umount -l ${rootfs_dir}/sys + fi + rm -rf ${rootfs_dir} + fi + mkdir ${rootfs_dir} + mkdir -p ${rootfs_dir}/var/lib/rpm + rpm --root ${rootfs_dir} --initdb + rpm -ivh --nodeps --root ${rootfs_dir}/ ${os_release_name} + if [[ ! -d ${rootfs_dir}/etc/yum.repos.d ]]; then + mkdir -p ${rootfs_dir}/etc/yum.repos.d + fi + cp ${cur_dir}/repo/*.repo $rootfs_dir/etc/yum.repos.d/ + dnf --installroot=${rootfs_dir}/ install dnf --nogpgcheck -y #--repofrompath=${repo_file_name},${rootfs_dir}/etc/yum.repos.d/${repo_file_name} + dnf --installroot=${rootfs_dir}/ makecache + dnf --installroot=${rootfs_dir}/ install -y wpa_supplicant vim net-tools iproute iputils NetworkManager openssh-server passwd hostname ntp + set +e + cat ${rootfs_dir}/etc/ntp.conf | grep "^server*" + if [ $? -ne 0 ]; then + echo -e "\nserver 0.cn.pool.ntp.org\nserver 1.asia.pool.ntp.org\nserver 2.asia.pool.ntp.org\nserver 127.0.0.1">>${rootfs_dir}/etc/ntp.conf + fi + cat ${rootfs_dir}/etc/ntp.conf | grep "^fudge*" + if [ $? -ne 0 ]; then + echo -e "\nfudge 127.0.0.1 stratum 10">>${rootfs_dir}/etc/ntp.conf + fi + set -e + cp ${cur_dir}/scripts/chroot.sh ${rootfs_dir}/chroot.sh + chmod +x ${rootfs_dir}/chroot.sh + mount --bind /dev ${rootfs_dir}/dev + mount -t proc /proc ${rootfs_dir}/proc + mount -t sysfs /sys ${rootfs_dir}/sys + chmod +x ${cur_dir}/scripts/chroot.sh + chroot ${rootfs_dir} /bin/bash -c "echo 'Y' | /chroot.sh" + umount -l ${rootfs_dir}/dev + umount -l ${rootfs_dir}/proc + umount -l ${rootfs_dir}/sys + cp ${cur_dir}/config/hosts ${rootfs_dir}/etc/hosts + # cp ${cur_dir}/config/resolv.conf $rootfs_dir/etc/resolv.conf + if [ ! -d $rootfs_dir/etc/sysconfig/network-scripts ]; then + mkdir -p $rootfs_dir/etc/sysconfig/network-scripts + fi + cp ${cur_dir}/config/ifup-eth0 $rootfs_dir/etc/sysconfig/network-scripts/ifup-eth0 + mkdir -p ${rootfs_dir}/lib/firmware + cp bluez-firmware/broadcom/* ${rootfs_dir}/lib/firmware/ + cp -r firmware-nonfree/brcm/ ${rootfs_dir}/lib/firmware/ + cp -r ${output_dir}/lib/modules ${rootfs_dir}/lib/ + rm ${rootfs_dir}/chroot.sh + LOG "make rootfs for ${repo_file} end." +} + +make_img(){ + LOG "make ${img_file} begin..." + cd "${run_dir}" + size=`du -sh --block-size=1MiB ${rootfs_dir} | cut -f 1 | xargs` + size=$(($size+1100)) + losetup -D + dd if=/dev/zero of=${img_file} bs=1MiB count=$size && sync + parted ${img_file} mklabel msdos mkpart primary fat32 8192s 593919s + parted ${img_file} -s set 1 boot + parted ${img_file} mkpart primary linux-swap 593920s 1593343s + parted ${img_file} mkpart primary ext4 1593344s 100% + device=`losetup -f --show -P ${img_file}` + LOG "after losetup: ${device}" + LOG "image ${img_file} created and mounted as ${device}" + # loopX=`kpartx -va ${device} | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1` + # LOG "after kpartx: ${loopX}" + kpartx -va ${device} + loopX=${device##*\/} + partprobe ${device} + bootp=/dev/mapper/${loopX}p1 + swapp=/dev/mapper/${loopX}p2 + rootp=/dev/mapper/${loopX}p3 + LOG "bootp: " ${bootp} "rootp: " ${rootp} + mkfs.vfat -n boot ${bootp} + mkswap ${swapp} + mkfs.ext4 ${rootp} + set +e + if [ -d ${root_mnt} ]; then + df -lh | grep ${root_mnt} + if [ $? -eq 0 ]; then + umount ${root_mnt} + fi + rm -rf ${root_mnt} + fi + if [ -d ${boot_mnt} ]; then + df -lh | grep ${boot_mnt} + if [ $? -eq 0 ]; then + umount ${boot_mnt} + fi + rm -rf ${boot_mnt} + fi + set -e + mkdir ${root_mnt} ${boot_mnt} + mount -t vfat -o uid=root,gid=root,umask=0000 ${bootp} ${boot_mnt} + mount -t ext4 ${rootp} ${root_mnt} + fstab_array=("" "" "" "") + for line in `blkid | grep /dev/mapper/${loopX}p` + do + uuid=${line#*UUID=\"} + fstab_array[${line:18:1}]=${uuid%%\"*} + done + echo "UUID=${fstab_array[3]} / ext4 defaults,noatime 0 0" > ${rootfs_dir}/etc/fstab + echo "UUID=${fstab_array[1]} /boot vfat defaults,noatime 0 0" >> ${rootfs_dir}/etc/fstab + echo "UUID=${fstab_array[2]} swap swap defaults,noatime 0 0" >> ${rootfs_dir}/etc/fstab + + cp -rf --preserve=mode,timestamps --no-preserve=ownership ${run_dir}/firmware/boot/* ${boot_mnt}/ + pushd ${boot_mnt}/ + rm -f *.dtb cmdline.txt kernel.img kernel7.img kernel7l.img + echo "console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait" > cmdline.txt + popd + cp --preserve=mode,timestamps --no-preserve=ownership ${output_dir}/Image ${boot_mnt}/kernel8.img + cp --preserve=mode,timestamps --no-preserve=ownership ${output_dir}/*.dtb ${boot_mnt}/ + cp --preserve=mode,timestamps --no-preserve=ownership ${output_dir}/overlays/* ${boot_mnt}/overlays/ + + if [ -f ${run_dir}/rootfs.tar ]; then + rm ${run_dir}/rootfs.tar + fi + cd ${rootfs_dir} + tar cpf ${run_dir}/rootfs.tar . + cd ${root_mnt} + tar xpf ${run_dir}/rootfs.tar -C . + cd "${run_dir}" + sync + sleep 10 + umount ${root_mnt} + umount ${boot_mnt} + + kpartx -d ${device} + losetup -d ${device} + + rm ${run_dir}/rootfs.tar + if [ -f ${img_file} ]; then + md5sum ${img_file} > ${img_file}.md5sum + xz -T 20 -z -c ${img_file} > ${img_file}.xz + md5sum ${img_file}.xz > ${img_file}.xz.md5sum + LOG "made sum files for ${img_file}" + fi + # rm -rf ${output_dir} + rm -rf ${rootfs_dir} + losetup -D + LOG "write ${img_file} done." + LOG "make ${img_file} end." +} + +IFS=$'\n' +prepare +update_firmware +update_kernel + +make_rootfs +make_img diff --git a/config/hosts b/config/hosts new file mode 100644 index 0000000000000000000000000000000000000000..832902498c200b703a6bb8851a2c62db0de8a099 --- /dev/null +++ b/config/hosts @@ -0,0 +1,2 @@ +127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 +::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 \ No newline at end of file diff --git a/config/ifup-eth0 b/config/ifup-eth0 new file mode 100644 index 0000000000000000000000000000000000000000..c91969b3e2066d7dda0c7d59794119403e0005f9 --- /dev/null +++ b/config/ifup-eth0 @@ -0,0 +1,16 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME=eth0 +UUID=851a6f36-e65c-3a43-8f4a-78fd0fc09dc9 +ONBOOT=yes +AUTOCONNECT_PRIORITY=-999 +DEVICE=eth0 \ No newline at end of file diff --git a/config/openEuler-1.0-LTS.repo b/config/openEuler-1.0-LTS.repo new file mode 100644 index 0000000000000000000000000000000000000000..558c4c09ca6ccbb1afd59881220a86fd669a771b --- /dev/null +++ b/config/openEuler-1.0-LTS.repo @@ -0,0 +1,17 @@ +[basiclocal] +name=basiclocal +baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/OS/aarch64/ +enabled=1 +gpgcheck=0 + +[srclocal] +name=srclocal +baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/source/ +enabled=1 +gpgcheck=0 + +[everythinglocal] +name=everythinglocal +baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/everything/aarch64/ +enabled=1 +gpgcheck=0 \ No newline at end of file diff --git "a/documents/images/\345\206\231\345\205\245SD.jpg" "b/documents/images/\345\206\231\345\205\245SD.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..92f0cbffd0c70631ab74d2e7e39a3e51d1b9ca69 Binary files /dev/null and "b/documents/images/\345\206\231\345\205\245SD.jpg" differ diff --git "a/documents/images/\346\240\274\345\274\217\345\214\226\345\211\215.jpg" "b/documents/images/\346\240\274\345\274\217\345\214\226\345\211\215.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..61fd4b86bb9d8db745496d08b8309c91a01a808c Binary files /dev/null and "b/documents/images/\346\240\274\345\274\217\345\214\226\345\211\215.jpg" differ diff --git "a/documents/images/\346\240\274\345\274\217\345\214\226\345\220\216.jpg" "b/documents/images/\346\240\274\345\274\217\345\214\226\345\220\216.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..37bc06b18121c03633ba6edb6bca827712c73c41 Binary files /dev/null and "b/documents/images/\346\240\274\345\274\217\345\214\226\345\220\216.jpg" differ diff --git "a/documents/images/\346\240\274\345\274\217\345\214\226\345\220\216\347\233\230.jpg" "b/documents/images/\346\240\274\345\274\217\345\214\226\345\220\216\347\233\230.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..8ac2750ca3a474357bea3f09bbbb7a2c84c90b29 Binary files /dev/null and "b/documents/images/\346\240\274\345\274\217\345\214\226\345\220\216\347\233\230.jpg" differ diff --git "a/documents/images/\347\231\273\345\275\225\346\240\221\350\216\223\346\264\276.jpg" "b/documents/images/\347\231\273\345\275\225\346\240\221\350\216\223\346\264\276.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..2d69a11243600972a833cdd42153f9b8b4d71d4a Binary files /dev/null and "b/documents/images/\347\231\273\345\275\225\346\240\221\350\216\223\346\264\276.jpg" differ diff --git "a/documents/images/\347\233\230\347\254\246.jpg" "b/documents/images/\347\233\230\347\254\246.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..b49213bd19cb5b9cdac6ce25564be17df2810d72 Binary files /dev/null and "b/documents/images/\347\233\230\347\254\246.jpg" differ diff --git "a/documents/images/\350\216\267\345\217\226IP.jpg" "b/documents/images/\350\216\267\345\217\226IP.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..100e330db48aa85b8af900056a31ecc794c97daf Binary files /dev/null and "b/documents/images/\350\216\267\345\217\226IP.jpg" differ diff --git "a/documents/openEuler\351\225\234\345\203\217\347\232\204\346\236\204\345\273\272.md" "b/documents/openEuler\351\225\234\345\203\217\347\232\204\346\236\204\345\273\272.md" new file mode 100644 index 0000000000000000000000000000000000000000..42a6e4b45439ca3b15a11d988acd1c561619c5d0 --- /dev/null +++ "b/documents/openEuler\351\225\234\345\203\217\347\232\204\346\236\204\345\273\272.md" @@ -0,0 +1,425 @@ +# 环境需求 + +- 操作系统:openEuler 或 Centos 7/8; +- 架构:ARM; +- 硬盘存储不低于50G; +- 内存不低于2G; +- 可访问外网。 + +可以通过以下方式获取 ARM 架构的运行环境: + +- 使用 ARM 架构的主机,例如树莓派 +- 使用 [QEMU](https://www.qemu.org/) 模拟器搭建 ARM 运行环境 + +# 树莓派相关 + +操作目录:${WORKDIR} + +## 编译内核 + +### 准备环境 + +- 操作系统:openEuler 或 Centos 7/8 +- 架构:ARM + +除了使用 ARM 架构的运行环境,也可以采用交叉编译的方式编译内核。这里,我们在 ARM 架构的服务器上编译内核。 + +### 下载源码 + +`git clone git@gitee.com:openeuler/raspberrypi-kernel.git` + +得到文件${WORKDIR}/raspberrypi-kernel。 + +### 进入内核目录 + +`cd ${WORKDIR}/raspberrypi-kernel` + +### 切换分支 + +这里适用于树莓派的 openEuler-1.0-LTS 内核源码的分支为 openEuler-1.0-LTS-raspi, + +`git checkout -b openEuler-1.0-LTS-raspi origin/openEuler-1.0-LTS-raspi` + +下面编译时可能还需要 bison、flex、build-essential 等,根据提示安装即可。 + +### 载入默认配置 + +`make ARCH=arm64 openeuler-raspi_defconfig` + +其中 openeuler-raspi_defconfig 在 ../linux/arch/arm64/configs 下。 + +### 编译 + +`make ARCH=arm64 -j4` + +### 创建编译内核模块目录 + +`mkdir ${WORKDIR}/ouput` + +### 编译内核模块 + +`make INSTALL_MOD_PATH=${WORKDIR}/output/ modules_install` + +在 ${WORKDIR}/output 文件夹下会生成 lib 文件夹。 + +### 收集编译结果 + +1. 内核 + +`cp ${WORKDIR}/raspberrypi-kernel/arch/arm64/boot/Image ${WORKDIR}/output/` + +2. 设备树文件等 + +`cp ${WORKDIR}/raspberrypi-kernel/arch/arm64/boot/dts/broadcom/*.dtb ${WORKDIR}/output/` + +`mkdir ${WORKDIR}/output/overlays` + +`cp ${WORKDIR}/raspberrypi-kernel/arch/arm64/boot/dts/overlays/*.dtb* ${WORKDIR}/output/overlays/` + +至此,所有内核及内核模块相关内容都在 ${WORKDIR}/output 下了。 + + +## 配置引导 + +### 下载引导 + +`cd ${WORKDIR}` + +`git clone --depth=1 https://github.com/raspberrypi/firmware` + +得到文件 ${WORKDIR}/firmware 。 + +### 进入引导目录 + +`cd ${WORKDIR}/firmware/boot` + +### 删除没有必要的文件 + +`rm *.dtb cmdline.txt kernel.img kernel7.img` + +### 添加cmdline.txt + +`touch cmdline.txt` + +写入新系统的内核参数: + +`console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait` + +## 树莓派固件 + +### 下载固件 + +1. 进入下载目录 + +`cd ${WORKDIR}` + +2. 下载 bluez-firmware + +`git clone --depth=1 https://github.com/RPi-Distro/bluez-firmware` + +得到文件 ${WORKDIR}/bluez-firmware。 + +3. 下载 firmware-nonfree + +`git clone --depth=1 https://github.com/RPi-Distro/firmware-nonfree` + +得到文件 ${WORKDIR}/firmware-nonfree。 + +# 制作openEuler的rootfs + +操作目录:${WORKDIR} + +## 创建RPM数据库 + +`mkdir ${WORKDIR}/rootfs` + +`mkdir -p ${WORKDIR}/rootfs/var/lib/rpm` + +`rpm --root ${WORKDIR}/rootfs/ --initdb` + +## 下载安装openEuler发布包 + +`rpm -ivh --nodeps --root /${WORKDIR}/rootfs/ http://repo.openeuler.org/openEuler-20.03-LTS/everything/aarch64/Packages/openEuler-release-20.03LTS-33.oe1.aarch64.rpm` + +会在 ${WORKDIR}/rootfs 下生成三个文件夹: + +etc/ usr/ var/ + +## 安装yum + +### 添加yum源 + +`mkdir ${WORKDIR}/rootfs/etc/yum.repos.d` + +`vim ${WORKDIR}/rootfs/etc/yum.repos.d/openEuler-20.03LTS.repo` + +添加内容: + +```[basiclocal] +name=basiclocal +baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/OS/aarch64/ +enabled=1 +gpgcheck=0 + +[srclocal] +name=srclocal +baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/source/ +enabled=1 +gpgcheck=0 + +[everythinglocal] +name=everythinglocal +baseurl=http://repo.openeuler.org/openEuler-20.03-LTS/everything/aarch64/ +enabled=1 +``` + +### 安装dnf + +`dnf --installroot=${rootfs_dir}/ install dnf --nogpgcheck -y` + +### 安装必要软件 + +`dnf --installroot=${rootfs_dir}/ makecache` + +`dnf --installroot=${rootfs_dir}/ install -y wpa_supplicant vim net-tools iproute iputils NetworkManager openssh-server passwd hostname ntp` + +## 添加配置文件 + +### 添加hosts + +`cp /etc/hosts ${WORKDIR}/rootfs/etc/hosts` + +### 网络相关 + +1. 设置DNS + +`cp -L /etc/resolv.conf ${WORKDIR}/rootfs/etc/resolv.conf` + +编辑添加nameserver: + +`vim ${WORKDIR}/rootfs/etc/resolv.conf` + +内容: +``` +nameserver 8.8.8.8 +nameserver 114.114.114.114 +``` + +2. 设置IP自动获取 + +`mkdir ${WORKDIR}/rootfs/etc/sysconfig/network-scripts` + +`vim ${WORKDIR}/rootfs/etc/sysconfig/network-scripts/ifup-eth0` + +内容: +``` +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME=eth0 +UUID=851a6f36-e65c-3a43-8f4a-78fd0fc09dc9 +ONBOOT=yes +AUTOCONNECT_PRIORITY=-999 +DEVICE=eth0 + +``` + +## rootfs设置 + +1. 挂载必要的路径 + +`mount --bind /dev ${WORKDIR}/rootfs/dev` + +`mount -t proc /proc ${WORKDIR}/rootfs/proc` + +`mount -t sysfs /sys ${WORKDIR}/rootfs/sys` + +2. run chroot + +`chroot ${WORKDIR}/rootfs /bin/bash` + +3. 启用开机自启ssh + +`systemctl enable ssh` + +4. 设置root密码 + +`passwd root` + +输入要设置的root密码 + +5. 设置主机名 + +`hostname OpenEuler` + +6. 退出 + +`exit` + +7. 取消临时挂载的目录 + +`umount -l ${WORKDIR}/rootfs/dev` + +`umount -l ${WORKDIR}/rootfs/proc` + +`umount -l ${WORKDIR}/rootfs/sys` + +# 制作镜像 + +## rootfs内容完善 + +### 将固件放进rootfs + +`mkdir -p /${WORKDIR}/rootfs/lib/firmware` + +`cp /${WORKDIR}/bluez-firmware/broadcom/* /${WORKDIR}/rootfs/lib/firmware/` + +`cp -r /${WORKDIR}/firmware-nonfree/brcm/ ${WORKDIR}/rootfs/lib/firmware/` + +### 将内核模块放进rootfs + +`cp -r /${WORKDIR}/output/lib/modules /${WORKDIR}/rootfs/lib/` + +## boot内容完善 + +### 将内核放进引导 + +`cp /${WORKDIR}/output/Image /${WORKDIR}/firmware/boot/kernel8.img` + +### 将dtb放进引导 + +`cp /${WORKDIR}/output/*.dtb /${WORKDIR}/firmware/boot/` + +## 生成镜像并分区挂载 + +### 计算镜像大小 + +`du -sh --block-size=1MiB /${WORKDIR}/rootfs` +`du -sh --block-size=1MiB /${WORKDIR}/firmware/boot` + +得到总大小略加1100MiB即可,将该大小记为 SIZE。 + +### 创建空镜像 + +`cd ${WORKDIR}` + +`dd if=/dev/zero of=openEuler_raspi.img bs=1M count=SIZE` + +其中 SIZE 为前面计算得到的计算镜像大小,最终生成空的镜像文件 ${WORKDIR}/openEuler_raspi.img。 + +### 使用 losetup 将磁盘镜像文件虚拟成快设备 + +`losetup -f --show openEuler_raspi.img` + +例如,显示结果为 /dev/loop0。 + +### 使用 kpartx 创建分区表 /dev/loop0 的设备映射 + +`kpartx -va /dev/loop0` + +得到结果将 /dev/loop0 三个分区挂载了: +``` +add map loop0p1 ... +add map loop0p2 ... +add map loop0p3 ... +``` + +运行`ls /dev/mapper/loop0p*`可以看到分区分别对应刚才为openEuler_raspi.img做的三个分区: + +``` +/dev/mapper/loop0p1 /dev/mapper/loop0p2 /dev/mapper/loop0p3 +``` + +### 格式化分区 + +1. 格式化 boot 分区 + +`mkfs.vfat -n boot /dev/mapper/loop0p1` + +2. 格式化交换分区 + +`mkswap /dev/mapper/loop0p2` + +3. 格式化根目录分区 + +`mkfs.ext4 /dev/mapper/loop0p3` + +### 创建要挂载的根目录和 boot 分区路径 + +`mkdir ${WORKDIR}/root ${WORKDIR}/boot` + +### 挂载根目录和 boot 分区 + +`mount -t vfat -o uid=root,gid=root,umask=0000 /dev/mapper/loop0p1 ${WORKDIR}/boot/` + +`mount -t ext4 /dev/mapper/loop0p3 ${WORKDIR}/root/` + +### 获取生成的 img 镜像的 blkid + +执行命令 blkid 得到三个分区的 UUID,例如: +``` +/dev/mapper/loop0p1: SEC_TYPE="msdos" LABEL="boot" UUID="2785-C7C3" TYPE="vfat" PARTUUID="e0a091bd-01" +/dev/mapper/loop0p2: UUID="a451bee4-4384-48a2-8d5a-d09c2dd9a1a2" TYPE="swap" PARTUUID="e0a091bd-02" +/dev/mapper/loop0p3: UUID="67b5fc1c-9cd3-4884-968c-4ca35e5ae154" TYPE="ext4" PARTUUID="e0a091bd-03" +``` + +## 修改 fstab + +`vim ${WORKDIR}/rootfs/etc/fstab` + +内容: +``` +UUID=67b5fc1c-9cd3-4884-968c-4ca35e5ae154 / ext4 defaults,noatime 0 0 +UUID=2785-C7C3 /boot vfat defaults,noatime 0 0 +UUID=a451bee4-4384-48a2-8d5a-d09c2dd9a1a swap swap defaults,noatime 0 0 +``` + +## rootfs 拷贝到镜像 + +`cd ${WORKDIR}/rootfs/` + +`tar cpf ${WORKDIR}/rootfs.tar .` + +`cd ${WORKDIR}/root` + +`tar xpf ${WORKDIR}/rootfs.tar -C .` + +## boot 引导拷贝到镜像 + +`cd ${WORKDIR}/firmware/boot` + +`tar cf ${WORKDIR}/boot.tar ./` + +`cd ${WORKDIR}/boot` + +`tar xf ${WORKDIR}/boot.tar -C .` + +## 卸载镜像 + +### 同步到盘 + +`sync` + +### 卸载 + +`umount ${WORKDIR}/root` + +`umount ${WORKDIR}/boot` + +### 卸载 loop0 挂载 + +`kpartx -d /dev/loop0` + +`losetup -d /dev/loop0` + +这样,最终就生成了需要的openEuler_raspi.img镜像文件。 + +之后就可以使用镜像刷写 SD 卡并使用树莓派了,详见 [树莓派刷机](./树莓派刷机.md) 和 [树莓派使用](./树莓派使用.md)。 \ No newline at end of file diff --git "a/documents/\346\240\221\350\216\223\346\264\276\344\275\277\347\224\250.md" "b/documents/\346\240\221\350\216\223\346\264\276\344\275\277\347\224\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..3bd6d2e2b6d5a72def9c579e070d6f91f12c6605 --- /dev/null +++ "b/documents/\346\240\221\350\216\223\346\264\276\344\275\277\347\224\250.md" @@ -0,0 +1,19 @@ +# 启用树莓派 + +版本要求:树莓派 3B/3B+/4B。 + +将刷好的 SD 卡插入树莓派,通电启用。树莓派正常启动,还需连接网线至局域网。 + +由于使用树莓派时,大多都使用 ssh 远程连接;在树莓派启动联网时,无法得知其 IP 地址。 + +有以下两种方式: + +1. 如果树莓派连接已知路由器,可登陆路由器管理,新增的IP即为树莓派IP: + +![](images/获取IP.jpg) + +2. 将树莓派连接显示器,需注意,树莓派视频输出接口为 Micro HDMI + +连接显示器后,直接用户名/密码登陆,登陆成功后,树莓派即显示本机相关信息,包括本机 IP。如下图(ssh登陆也显示这些信息): + +![](images/登录树莓派.jpg) \ No newline at end of file diff --git "a/documents/\346\240\221\350\216\223\346\264\276\345\210\267\346\234\272.md" "b/documents/\346\240\221\350\216\223\346\264\276\345\210\267\346\234\272.md" new file mode 100644 index 0000000000000000000000000000000000000000..2218ea5b50d3b9e166e8188c2ce1d6864baabc41 --- /dev/null +++ "b/documents/\346\240\221\350\216\223\346\264\276\345\210\267\346\234\272.md" @@ -0,0 +1,110 @@ +# 树莓派刷机 + +## 实验环境 + +- Windows10/Linux/Mac +- 树莓派 3B/3B+/4B +- 16G 以上的 Micro SD 卡 + + +## 获取树莓派 img 镜像 + +下载适配树莓派的最新openEuler镜像,下面以XXX.img表示该镜像。 + +## 刷机操作 + +下面分别介绍 Windows、Linux、Mac 下的刷机步骤。 + +### Windows 环境 + +#### 格式化 SD 卡 + +下载应用:SDFormater,用于格式化 SD 卡。 + +若 SD 卡之前未安装过镜像,盘符正常只有一个,选择 SD 卡对应盘符,直接格式化即可; + +若 SD 卡之前安装过镜像,盘符会有三个,选择 SD 卡对应盘符(图例中为 E: 盘),格式化即可: + +![](images/盘符.jpg) + +![](images/格式化前.jpg) + +![](images/格式化后.jpg) + +![](images/格式化后盘.jpg) + +#### 写入 SD 卡 + +- 下载应用:Win32 Disk Imager。 +- 右键选择“以管理员身份运行”,打开 Win32 Disk Imager,选择镜像 img 文件和待写入的 SD 卡,点击【写入/Write】。 + +![](images/写入SD.jpg) + +写入完成即可。 + +写入成功后,SD 卡自动分区后的盘符为: + +![](images/盘符.jpg) + +使用时的系统大小为 boot 盘的大小,根据使用需求,可用 gparted 工具为 boot 盘扩容。 + +### Linux 环境 + +#### 查看磁盘分区信息 + +`fdisk -l` + +获取 SD 卡磁盘信息,例如 SD 卡对应磁盘为 /dev/sdb。 + +#### 卸载 SD 卡挂载点 + +查看当前已挂在的卷 + +`df -lh` + +例如,SD 卡对应磁盘两个分区 /dev/sdb1 和 /dev/sdb3 默认已挂载。 +卸载对应分区: + +`umount /dev/sdb1` + +`umount /dev/sdb3` + +#### 写入 SD 卡 + +将下载的镜像 XXX.img 刷入 SD 卡。 + + +`dd bs=4M if=XXX.img of=/dev/sdb` + +### Mac 环境 + +#### 查看磁盘分区信息 + +`diskutil list` + +获取 SD 卡磁盘信息,例如 SD 卡对应磁盘为 /dev/disk3。 + +#### 卸载 SD 卡挂载点 + +查看当前已挂在的卷 + +`df -lh` + +例如,SD 卡对应磁盘两个分区 /dev/disk3s1 和 /dev/disk3s3 默认已挂载。 +卸载对应分区: + +`diskutil umount /dev/sdb1` + +`diskutil umount /dev/sdb3` + +#### 写入 SD 卡 + +将下载的镜像 XXX.img 刷入 SD 卡。 + + +`dd bs=4m if=XXX.img of=/dev/sdb` + + +## 树莓派使用 + +SD 卡刷好镜像之后,就可以使用树莓派了,详见 [树莓派使用](./树莓派使用.md)。 \ No newline at end of file diff --git a/scripts/chroot.sh b/scripts/chroot.sh new file mode 100644 index 0000000000000000000000000000000000000000..47440fc426632f5204892686912ceba7c8f8f9ee --- /dev/null +++ b/scripts/chroot.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e +systemctl enable sshd +systemctl enable ntpd +hostname OpenEuler +echo "openeuler" | passwd --stdin root