Mặc định, RPi đã có hai kiểu boot: SD boot và USB boot. Tuy nhiên, USB boot không được cho phép theo mặc định, vì nó cần một ít chuẩn bị trước khi có thể hoạt động.
Mới đây, raspberrypi.org đã đưa ra giải pháp cho phép khởi động từ các ổ đĩa USB. Tuy nhiên, mọi việc không thực sự dễ dàng như thể cài đặt rồi cắm và chạy, nó còn phụ thuộc vào ổ đĩa USB có phù hợp hay không (về nguồn điện, thời gian khởi động của ổ đĩa, tốc độ đọc ghi, firmware…)
Trong bài là script giúp tự động tạo đĩa usb để có thể khởi động từ đó.
Chuẩn bị
- RPi
- Micro USB đã cài đặt hoàn chỉnh Raspbian
- USB flash/SSD
Thực hành
Khởi động RPi với thẻ Micro SD, sau đó cắm USB flash/SSD vào RPi. Nếu chỉ có duy nhất một ổ đĩa USB được cắm vào RPi thì tên ổ đĩa là /dev/sda. Nếu có nhiều ổ USB cắm vào RPi thì dùng lệnh fdisk -l hay mount để nhận biết tên ổ đĩa.
Cú pháp tạo đĩa khởi động là
usbBoot [deviceName] [partitionSize]
deviceName là tên ổ đĩa USB, có thể là /dev/sda hay /dev/sdb…
Script sẽ tạo 2 phân vùng trên ổ đĩa USB, boot (FAT32) dung lượng 64M và OS (ext4) dung lượng là 100% dung lượng còn lại hay partitionSize (tính bằng %, hay M hay G)
Nếu chỉ chạy lệnh usbBoot thì ổ đĩa USB mặc định là /dev/sda và dung lượng OS partition là 100% phần đĩa còn lại
Script chạy trong khoảng thời gian từ 10 phút đến hơn 30 phút, tùy thuộc tốc độ ghi của ổ đĩa USB và kết thúc với dòng nhắc
Chạy lệnh sudo poweroff để tắt RPi... Tháo Micro SD card và tắt/mở điện để khởi động RPi từ USB...
#!/bin/bash #--usbBoot script -------------- #--Tác giả: lnt <lnt@lyle.info> if [ "$#" -eq 0 ]; then usb='/dev/sda' siz='100%' elif [ "$#" -eq 1 ]; then if [[ "$1" =~ \d*[%MG] ]]; then siz=$1 usb='/dev/sda' else usb=$1 siz='100%' fi elif [ "$#" -eq 2 ]; then if [[ "$1" =~ \d*[%MG] ]]; then siz=$1 usb=$2 else usb=$1 siz=$2 fi else echo 'Chuẩn bị USB để khởi động RPi' echo "usage: $(basename $0) [device] [partition_size]" exit fi if [ -z "$(sudo blkid $usb)" ]; then echo "Vui lòng cắm $usb vào RPi" exit fi echo 'Cập nhật OS...' echo sudo apt-get update sudo BRANCH=next rpi-update echo program_usb_boot_mode=1 | sudo tee -a /boot/config.txt &> /dev/null echo echo 'Umount các thư mục/phân vùng liên quan...' for f in $(mount | grep -Po "(?<=${usb}[1-9] on )[^ ]+" | sort -r); do sudo umount $f; done echo echo "Phân chia đĩa ${usb}, P1 64M và P2 $siz..." echo sudo parted -s ${usb} mklabel msdos sudo parted -a optimal -s ${usb} mkpart primary fat32 0% 64M sudo parted -a optimal -s ${usb} mkpart primary ext4 64M $siz sudo mkfs.vfat -n BOOT -F 32 ${usb}1 sudo mkfs.ext4 -F ${usb}2 [ ! -d /mnt/target ] && sudo mkdir /mnt/target || sudo umount /mnt/target &> /dev/null sudo mount ${usb}2 /mnt/target [ ! -d /mnt/target/boot ] && sudo mkdir /mnt/target/boot || sudo umount /mnt/target/boot &> /dev/null sudo mount ${usb}1 /mnt/target/boot echo echo 'Chép boot/OS vào USB. Có thể mất vài mươi phút...' echo sudo rsync -avx --delete / /boot /mnt/target sudo sed -i "s,root=/dev/mmcblk0p2,root=${usb}2," /mnt/target/boot/cmdline.txt sudo sed -i "s,/dev/mmcblk0p,${usb},g" /mnt/target/etc/fstab echo echo 'Tạo lại ssh host keys...' cd /mnt/target sudo mount --bind /dev dev sudo mount --bind /sys sys sudo mount --bind /proc proc cat <<EOF | sudo chroot /mnt/target rm /etc/ssh/ssh_host* dpkg-reconfigure openssh-server wait EOF sudo umount dev sudo umount sys sudo umount proc cd ~ #sudo umount /mnt/target/boot #sudo umount /mnt/target echo 'Chạy lệnh sudo poweroff để tắt RPi' echo 'Tháo Micro SD card và tắt/mở điện để khởi động RPi từ USB' #sudo poweroff
Chú thích
- Test nhanh
Sau 3 câu lệnhsudo apt-get update sudo BRANCH=next rpi-update echo program_usb_boot_mode=1 | sudo tee -a /boot/config.txt &> /dev/null
thì Micro SD card đang dùng trên RPi đã được bổ sung các file cần thiết để khởi động từ USB, chỉ phải đổi tên các partition
a. Trong /boot/cmdline.txt, đổi /dev/mmcblk0p2 thành /dev/sda2
b. Trong /etc/fstab, đổi /dev/mmcblk0p1 thành /dev/sda1, /dev/mmcblk0p2 thanh /dev/sda2
Công việc này có thể làm thủ công hay qua 2 câu lệnh sau:sudo sed -i "s,root=/dev/mmcblk0p2,root=/dev/sda2," /boot/cmdline.txt sudo sed -i "s,/dev/mmcblk0p,/dev/sda,g" /etc/fstab
Nếu tháo Micro SD card này (tôi đang dùng thẻ Sandisk 16GB hay Samsung 8GB) gắn vào một đầu đoc thẻ và gắn đầu đọc này vào cổng USB của RPi thì có thể khởi động từ USB (đầu đọc thẻ Trancend 3.0)
- Không thể khởi động từ USB?
raspberrypi.org không cam đoan là có thể khởi động được từ mọi ổ đĩa USB, mọi việc đang trong giai đoạn hoàn thiện. Hãy nối RPi với một màn hình, chúng ta sẽ quan sát quá trình khởi động rõ hơn. Nếu do ổ đĩa USB, đèn data trên RPi và đèn USB sẽ không chớp, quá trình khởi động đã dừng ở một bước nào đó, thông thường ở bước kết nối với ổ đĩa USB. Với ổ đĩa GPT, quá trình khởi động sẽ dừng ở màn hình cầu vòng. Hiện nay chỉ khởi động được với ổ đĩa MBR. - Khởi động từ USB chậm hơn từ Micro SD card?
Một số người dùng cho biết khởi động từ USB chậm, đó là vì RPi phải quét qua từng ổ đĩa USB để tìm file khởi động bootcode.bin, có thể vẫn để thẻ SD card trống không ở RPi để giảm 5 giây tìm kiếm. - Không thể kết nối qua SSH?
Cắm USB vào một máy Linux (RPi) và chạy đoạn mã tạo lại SSH như sau (copy và dán vào màn hình SSH)
[ ! -d /mnt/target ] && sudo mkdir /mnt/target || sudo umount /mnt/target &> /dev/null sudo mount /dev/sda2 /mnt/target/ [ ! -d /mnt/target/boot ] && sudo mkdir /mnt/target/boot || sudo umount /mnt/target/boot &> /dev/null sudo mount /dev/sda1 /mnt/target/boot cd /mnt/target sudo mount --bind /dev dev sudo mount --bind /sys sys sudo mount --bind /proc proc sudo chroot /mnt/target sudo rm /etc/ssh/ssh_host* sudo dpkg-reconfigure openssh-server exit sudo umount dev sudo umount sys sudo umount proc cd ~ sudo umount /mnt/target/boot sudo umount /mnt/target
5. Nếu boot từ HDD, có thể phải cấp nguồn cho RPi với công suất lớn hơn 2.5A (5V) vì HDD có thể cần nguồn lớn khi khởi động. Trong khi đó, nhiều SSD có thể khởi động với nguồn 2.5A
Hãy nghĩ ngay đến dòng điện cung cấp cho RPi nếu không thể khởi động.
6. Để thẻ nhớ đầy đủ phân vùng khởi động trong RPi có thể khiến RPi khởi động từ thẻ nhớ, sau đó theo fstab mà mount sda1 thành /boot và sda2 thành OS. Điều này khiến chúng ta dễ hiểu lầm là RPi được boot từ USB, tuy nhiên cả 2 phân vùng của thẻ nhớ đều được mount như phân vùng data. Chẳng có gì xảy ra cho đến khi chúng ta cài đặt gì đó có ghi vào phân vùng boot (như bật I2C), các thay đổi này được ghi vào sda1 thay vì mmcblk0p1 và không có tác dụng.