Update 2019/09
时隔一年,现在Ubuntu Server官方已经有预安装的镜像了,直接刷入镜像启动就可以了,也没有了本文遇到的各种奇怪的问题,没有必要进行以下操作了。但博客内容还是保留以作参考。官方镜像使用的是linux-raspi2内核(而不是generic内核)。最新操作指南请参见官方网站
以下是博客原文
树莓派真是个神奇的玩意,我手上的树莓派3B,小小身材却搭载了一颗64位的ARM-v8架构处理器,Wi-Fi、蓝牙、以太网、USB啥都不少。但可惜的是官方提供的Raspbian系统却只有32位的版本。本着极客的精神,当然要让手头的硬件发挥出它最大的实力啦。我找了一下,发现Ubuntu的wiki上有相关的内容,于是我就选择安装Ubuntu Server版本啦。
准备安装SD卡
本次安装我只使用了SD卡,一来是方便,不用额外准备安装U盘了,二来,树莓派的USB启动我搞了一下午也没搞定😟。绝大多数文件将会在安装过程中从网上下载。
以下操作建议在Linux系统中完成,本人使用的是虚拟机中的Ubuntu Desktop 18.04.1版本。
以下操作将清除SD卡中的全部数据
分区
首先,使用GParted对SD卡进行分区,新建一个msdos分区表(树莓派似乎不能启动GPT分区表的SD卡),然后新建一个128MB的FAT32分区,并设置boot标志。这个分区将用来放置树莓派的bootloader,u-boot和Ubuntu网络安装程序,安装完成后,这个分区将作为系统的EFI启动分区使用。其他的空间保持空闲即可。
以下假设新的FAT32分区挂载于/mnt
。
安装树莓派的bootloader文件
wget http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-bootloader_1.20180817-1_armhf.deb
dpkg-deb -x raspberrypi-bootloader_1.20180817-1_armhf.deb pi-bootloader
sudo cp pi-bootloader/boot/* /mnt
在安装时可视情况选择最新版本的bootloader安装。
编译并安装u-boot
sudo apt-get install build-essential bc gcc-aarch64-linux-gnu
wget ftp://ftp.denx.de/pub/u-boot/u-boot-2018.07.tar.bz2
tar -axf u-boot-2018.07.tar.bz2
cd u-boot-2018.07
export CROSS_COMPILE=aarch64-linux-gnu-
make rpi_3_defconfig
make all
sudo cp u-boot.bin /mnt/kernel8.img
cd ..
在安装时可视情况选择最新版本的u-boot安装。我们把编译好的镜像命名为kernel8.img
,这样上一步安装的bootloader就会自动以64位模式运行这个文件。
安装dtb文件(device tree blob)
wget http://ports.ubuntu.com/dists/bionic/main/installer-arm64/current/images/device-tree/bcm2837-rpi-3-b.dtb
sudo mkdir -p /mnt/dtb/broadcom/
sudo cp bcm2837-rpi-3-b.dtb /mnt/dtb/broadcom
u-boot应该会在启动的时候自动识别这是树莓派3B,然后自动加载这个文件的。(未经证实)
安装Ubuntu网络安装程序
去 https://www.ubuntu.com/download/server/arm 下载网络安装程序的iso文件,直接将iso文件里的所有文件复制到SD卡上,别漏了隐藏的.disk
文件夹。
恰好iso文件里boot/grub/efi.img
镜像内的文件可以用于启动这个网络安装程序(我也不知道为何)。挂载这个镜像,然后把efi
文件夹复制到SD卡根目录即可。
以下为命令行操作流程。
mkdir /tmp/mini-iso
sudo mount -o loop mini.iso /tmp/mini-iso
sudo cp -rT /tmp/mini-iso /mnt
mkdir /tmp/efi-img
sudo mount -o loop /tmp/mini-iso/boot/grub/efi.img /tmp/efi-img
sudo cp -rT /tmp/efi-img /mnt
sync
sudo umount /tmp/efi-img
sudo umount /tmp/mini-iso
sudo umount /mnt
安装Ubuntu系统
OK,将SD卡插入树莓派,然后启动。不出意外的话,根据提示一步一步安装就好了。安装时,不要改变一开始创建的FAT32分区,并在空闲空间里创建EXT4分区安装系统。在安装引导程序的时候应该会失败,没关系,我们后面会手动解决这个问题。这里选择不安装引导程序并继续。这时系统就安装好了,虽然不能自动引导启动。
手动引导系统
再次启动树莓派,这次不要选择安装,而是按c进入shell。如果你的分区和我一样的话,输入set root=(hd0,msdos3)
来设置根目录位置,否则,你应该使用ls命令来找出合适的分区。如果设置正确的话,输入ls \
应该你会看到Linux根目录的典型结构 (/var, /root, /usr, /bin, /etc, ...)
接下来使用以下命令引导系统启动。(你可能需要视情况修改root参数)
linux /boot/vmlinuz root=/dev/mmcblk0p2
initrd /boot/initrd.img
boot
我输入initrd指令之后好像等了很久,boot我也不知道我到底有没有输入进去,总之我是成功启动了。
构建自动引导
之后,我们打算将一开始创建的FAT32分区改造成EFI启动分区使用,首先要将那个分区挂载到/boot/efi
下。
sudo mkdir /boot/efi
sudo mount /dev/mmcblk0p1 /boot/efi
然后修改/etc/fstab
文件好让Linux在启动时自动挂载这个分区。
之后,我们之前网络安装程序放在FAT32分区里的文件就没啥用了,你可以删掉,但不删也没啥问题。
sudo grub-install --no-nvram
sudo update-grub
这样Ubuntu就帮我们设置好了grub引导程序了,并且会在更新系统内核时自动更新引导,十分方便。
终于!这样我们就有了一个基本可用的Ubuntu Server了。重启试试吧。
疑难杂症
Wi-Fi
刚刚安装好的系统,Wi-Fi似乎还是不太好使,更新以下相关的驱动程序即可。
# Pi 3B wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43430-sdio.bin wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43430-sdio.txt # Pi 3B+ # wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43455-sdio.bin # wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43455-sdio.clm_blob # wget https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43455-sdio.txt sudo cp *sdio* /lib/firmware/brcm/
之后需要使用
dpkg-divert
来防止linux-firmware
包更新的时候覆盖我们手动下载的文件。重启一下,Wi-Fi就可用了。顺带一提,在Ubuntu 18.04下,使用netplan来设置Wi-Fi是比较方便的。引导启动时的键盘失灵
我在u-boot和grub启动阶段,我的键盘都没法使用。经过多次尝试,发现只有使用我舍友的键盘,插再我的显示器上,再把显示器的USB线插在树莓派上才行(神奇)。如果你也遇到这样的问题并没法解决的话,可以改一下
grub.cfg
文件,加入一个set timeout=10
。这样10秒后如果没有操作,它就会自动启动默认选项了。奇怪的显示器黑屏
在使用的过程中,时常会出现黑屏的现象。我总结规律后发现,此时总是树莓派的红色电源指示灯会闪一下,屏幕右上角会出现一个闪电⚡的标志,这是电压不足的表现。这时只要切换一下tty就可以恢复正常。事后查看系统日志也未发现任何异常,而官方的操作系统则不会有这个现象,非常奇怪。目前解决方法就是,换一个更好的电源适配器为树莓派供电。
安装期间的网络
现在越来越多人都一直在用无线联网了,可是在树莓派的Wi-Fi可用之前,有不少操作都需要网络,如果这时手头又没有网线/路由器之类的设备,就很令人头大了。感谢电信学院的师兄提供的线索,我们可以用手机的USB网络共享功能,非常方便,手机用USB线连接树莓派后开启此功能,树莓派就可以上网了,完全不用配置。但这带来了另一个问题,树莓派由于要给手机充电,它的供电就更加不稳定了。所以,可能的话,先给手机充满电吧。
键盘上的大写锁定灯不会亮,不知道什么问题,不过不影响使用,大写锁定还是能正常开启的。
调整分区大小带来的问题
这事简直太神奇了,我一开始安装的时候,给FAT32分区分了1G空间,发现太大了,想弄小一点。但是GParted对FAT32的支持不是很好,我实用了一些非常规的操作。我先把FAT32分区所有文件备份,然后格式化为EXT4,然后再调整分区大小为128M,同时把安装系统的分区向左移动并扩大,最后把128M的分区重新格式化为FAT32并把文件复制回去。看上去好像还好,可是却出了一堆问题。。
首先,它没法启动了,显示了一点内核输出的日志,然后就卡住了,也没见错误信息。好吧,我把存储卡挂载回电脑上,并使用qemu+chroot尝试运行存储卡里的程序,可是,就算是ls这样简单的指令也会报错,加载一个
libselinux.so.1
文件时报invalid ELF header
,起初我还以为是动态链接器的缓存问题(之前遇到过),但是file
查看这个文件,竟然报告是data
(正常应该是shared object啥的), 看上去这个文件是的确损坏了。好吧,我去Linux的安装包里把这个文件拉出来替换上去,顺便用grub-install
重新安装了一下引导(GParted提示我了可能会损坏引导)。再次尝试启动,进入了emergency mode。看了一堆日志以后,看到文件系统检查发现FAT32分区损坏。我也不知道为啥。。
dosfsck
程序帮我修复了这个问题,空闲块汇总信息不对。再试一次,还是emergency mode。。好吧,由于重新格式化了分区,UUID变了,改下
fstab
文件就好了吧。OK,再来,终于进入系统了,而且没看到啥报错。但是之前有那个so文件损坏了,我估计肯定还有其他文件损坏吧,于是我用
debsums
检查了一遍,果然又找出了五、六个损坏的文件,我用apt把受到影响的包重新安装了,看上去是没有啥问题了。但最初这些文件为何会损坏还是不得而知(GParted的bug吗?)。linux-raspi2内核
Ubuntu有个包叫linux-raspi2,似乎这是一个专门为树莓派设计的内核呢,我当然要实验一下。可是,安装了这个包之后,就没法启动了,似乎这个内核还不支持grub?附带吐槽一下写各个报错信息的同学“回滚启动项”五个字写错了两个。
但我任然不死心,那我就不用grub试试咯。Ubuntu还有个叫
flash-kernel
的包,它负责写入必要的文件到固件中。这个包的数据库里有树莓派的记载,flash-kernel
将会把内核,内存盘,以及一个一个uboot的脚本写入/boot/firmware
。于是,我把我的FAT32分区挂载到这里,并运行flash-kernel
,但是并没有办法启动,有好多错误,包括magic number不正确,未知的bootz命令。我在编译时手动加入了bootz支持,但magic number不正确的错误依然无法解决,实在不知为何,难道要用特制的u-boot才能启动吗?最后我放弃了这个实验。flash-kernel带来的麻烦
正是由于flash-kernel的数据库里有树莓派,即使你用grub启动的,并不需要它,它也会在内核更新时插一手,反而还会因为找不到一些文件而导致内核更新失败。这时我们就要告诉flash-kernel不需要它了,使用
echo -n none | sudo tee /etc/flash-kernel/machine
,就能达到这个目的。
结束语
弄了这么多,我要用这个新系统来干什么呢?我也没想好😞。不过,搞这个的目的也许并不在于结果,而就在于折腾的本身吧。在折腾的过程中,我对系统各个组件的了解都有所加深了呢。
或许,我可以做一个校园网内网访问,速度非常快的收作业系统?