Difference between revisions of "SD Card"

From krtkl wiki
Jump to navigation Jump to search
Line 1: Line 1:
 +
== Linux SD Card Build Script ==
  
== Formatting SD Card ==
+
<pre>
 +
$ export SD_CARD_IMG=snickerdoodle_xenial_kinetic.img
 +
$ export SD_CARD_DEV=/dev/sdb
 +
$ ./sd_create.sh
 +
</pre>
 +
 
 +
<pre>
 +
#!/bin/bash
  
Use <tt>fdisk</tt> to format the SD card.
+
# Check if the card device variable has been set
 +
if [ -z "${SD_CARD_DEV}" ]; then
 +
        echo "[ERROR]: SD_CARD_DEV is unset"
 +
        exit
 +
elif [ -z "${SD_CARD_IMG}" ]; then
 +
        echo "[ERROR]: SD_CARD_IMG is unset"
 +
        exit
 +
fi
  
=== Locating SD Card on System ===
+
# Check if the card device has mounted partitions
 +
if [ $(mount | grep -c "${SD_CARD_DEV}[0-9]*") != "0" ]; then
 +
        echo "SD card has mounted partitions -> unmounting"
 +
        mount | grep -o "${SD_CARD_DEV}[0-9]*" | xargs umount -n
  
The <tt>mount</tt> command can be used to locate the SD card device, once it has been connected to the host computer. In the example below, an SD card has been connected on <tt>/dev/sdb1</tt> and mounted at <tt>/media/user/UNTITLED</tt>.
+
        if [ $? -ne 0 ]; then
 +
                echo "[ERROR]: Failed to unmount existing partitions"
 +
                exit
 +
        fi
  
<pre style="margin-bottom: 0; border-bottom:none; padding-bottom:0.8em;">$ mount</pre>
+
        sleep 3
<pre style="margin-top: 0; border-top-style:dashed; padding-top: 0.8em;">
+
fi
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
+
 
proc on /proc type proc (rw,noexec,nosuid,nodev)
+
# Create a new partition table for the card
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
+
parted ${SD_CARD_DEV} --script -- mklabel msdos
none on /sys/fs/cgroup type tmpfs (rw)
+
parted ${SD_CARD_DEV} --script -- mkpart primary fat32 1MiB 128MiB
none on /sys/fs/fuse/connections type fusectl (rw)
+
parted ${SD_CARD_DEV} --script -- mkpart primary ext4 128MiB 100%
none on /sys/kernel/debug type debugfs (rw)
+
 
none on /sys/kernel/security type securityfs (rw)
+
sleep 3
udev on /dev type devtmpfs (rw,mode=0755)
+
 
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
+
bootp=${SD_CARD_DEV}1
tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
+
rootfsp=${SD_CARD_DEV}2
none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)
+
 
none on /run/shm type tmpfs (rw,nosuid,nodev)
+
mkfs.vfat -n BOOT ${bootp}
none on /run/user type tmpfs (rw,noexec,nosuid,nodev,size=104857600,mode=0755)
+
mke2fs -t ext4 -L ROOTFS -b 4096 ${rootfsp}
none on /sys/fs/pstore type pstore (rw)
+
 
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev)
+
# Can we mount the new partitions is a repeatable way?
systemd on /sys/fs/cgroup/systemd type cgroup (rw,noexec,nosuid,nodev,none,name=systemd)
+
bootpmnt=$(mktemp -d sdbootXXX)
gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,user=russellbush)
+
rootfspmnt=$(mktemp -d sdrootfsXXX)
/dev/sdb1 on /media/user/UNTITLED type vfat (rw,nosuid,nodev,uid=1000,gid=1000,shortname=mixed,dmask=0077, utf8=1,showexec,flush,uhelper=udisks2)
+
 
 +
mount ${bootp} ${bootpmnt}
 +
mount ${rootfsp} ${rootfspmnt}
 +
 
 +
# Mount the image for dumping
 +
loopdevice=$(losetup -f --show ${SD_CARD_IMG})
 +
if [ $? -ne 0 ]; then
 +
        echo "[ERROR]: failed to setup loop device for ${SD_CARD_IMG}"
 +
        exit
 +
fi
 +
 
 +
device=$(kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1)
 +
 
 +
sleep 5
 +
 
 +
# Set up the mapped boot and rootfs partitions of the image
 +
device="/dev/mapper/${device}"
 +
imgbootp=${device}p1
 +
imgrootfsp=${device}p2
 +
 
 +
# Make mount point directories
 +
imgbootpmnt=$(mktemp -d sdbootXXX)
 +
imgrootfspmnt=$(mktemp -d sdrootfsXXX)
 +
 
 +
mount ${imgbootp} ${imgbootpmnt}
 +
mount ${imgrootfsp} ${imgrootfspmnt}
 +
 
 +
# Rsync contents of the boot and rootfs partitions to the SD card
 +
rsync -Hav --progress ${imgbootpmnt}/ ${bootpmnt}
 +
rsync -Hav --progress ${imgrootfspmnt}/ ${rootfspmnt}
 +
 
 +
sync
 +
 
 +
umount ${imgbootp}
 +
umount ${imgrootfsp}
 +
 
 +
rm -r ${imgbootpmnt}
 +
rm -r ${imgrootfspmnt}
 +
 
 +
echo "--- Removing loop device"
 +
kpartx -dv ${loopdevice}
 +
losetup -d ${loopdevice}
 +
 
 +
umount ${bootp}
 +
umount ${rootfsp}
 +
rm -r ${bootpmnt}
 +
rm -r ${rootfspmnt}
 +
 
 +
eject ${SD_CARD_DEV}
 
</pre>
 
</pre>
 +
 +
== Manual SD Card Disk Layout ==
  
 
=== Partitioning the SD Card (<tt>fdisk</tt>) ===
 
=== Partitioning the SD Card (<tt>fdisk</tt>) ===
Line 141: Line 212:
 
If the formatting is successful, the following output with be written to the console (writing superblocks and filesystem accounting information can take some time depending on the size and speed of the SD card):
 
If the formatting is successful, the following output with be written to the console (writing superblocks and filesystem accounting information can take some time depending on the size and speed of the SD card):
  
<pre style="margin-bottom: 0; border-bottom:none; padding-bottom:0.8em;">$ mke2fs -b 1024 -t ext4 -L ROOTFS /dev/sdb2</pre>
+
<pre style="margin-bottom: 0; border-bottom:none; padding-bottom:0.8em;">$ mke2fs -b 4096 -t ext4 -L ROOTFS /dev/sdb2</pre>
 
<pre style="margin-top: 0; border-top-style:dashed; padding-top: 0.8em;">
 
<pre style="margin-top: 0; border-top-style:dashed; padding-top: 0.8em;">
 
mke2fs 1.42.9 (4-Feb-2014)
 
mke2fs 1.42.9 (4-Feb-2014)
Line 175: Line 246:
 
=== Boot Partition Components ===
 
=== Boot Partition Components ===
  
==== Copy Boot Partition Images to Card ====
+
* boot.bin (FSBL/U-Boot)
 +
* boot.script.img (system boot script)
 +
* devicetree.dtb (device tree blob)
 +
* uEnv.txt (U-Boot supplementary environment definition)
 +
* uImage (Linux kernel image)
  
  
 
=== Rootfs Partition ===
 
=== Rootfs Partition ===
  
==== Extract Filesystem to Rootfs Partition ====
+
[[Root Filesystem]]

Revision as of 03:35, 25 January 2018

Linux SD Card Build Script

$ export SD_CARD_IMG=snickerdoodle_xenial_kinetic.img
$ export SD_CARD_DEV=/dev/sdb
$ ./sd_create.sh
#!/bin/bash

# Check if the card device variable has been set
if [ -z "${SD_CARD_DEV}" ]; then
        echo "[ERROR]: SD_CARD_DEV is unset"
        exit
elif [ -z "${SD_CARD_IMG}" ]; then
        echo "[ERROR]: SD_CARD_IMG is unset"
        exit
fi

# Check if the card device has mounted partitions
if [ $(mount | grep -c "${SD_CARD_DEV}[0-9]*") != "0" ]; then
        echo "SD card has mounted partitions -> unmounting"
        mount | grep -o "${SD_CARD_DEV}[0-9]*" | xargs umount -n

        if [ $? -ne 0 ]; then
                echo "[ERROR]: Failed to unmount existing partitions"
                exit
        fi

        sleep 3
fi

# Create a new partition table for the card
parted ${SD_CARD_DEV} --script -- mklabel msdos
parted ${SD_CARD_DEV} --script -- mkpart primary fat32 1MiB 128MiB
parted ${SD_CARD_DEV} --script -- mkpart primary ext4 128MiB 100%

sleep 3

bootp=${SD_CARD_DEV}1
rootfsp=${SD_CARD_DEV}2

mkfs.vfat -n BOOT ${bootp}
mke2fs -t ext4 -L ROOTFS -b 4096 ${rootfsp}

# Can we mount the new partitions is a repeatable way?
bootpmnt=$(mktemp -d sdbootXXX)
rootfspmnt=$(mktemp -d sdrootfsXXX)

mount ${bootp} ${bootpmnt}
mount ${rootfsp} ${rootfspmnt}

# Mount the image for dumping
loopdevice=$(losetup -f --show ${SD_CARD_IMG})
if [ $? -ne 0 ]; then
        echo "[ERROR]: failed to setup loop device for ${SD_CARD_IMG}"
        exit
fi

device=$(kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1)

sleep 5

# Set up the mapped boot and rootfs partitions of the image
device="/dev/mapper/${device}"
imgbootp=${device}p1
imgrootfsp=${device}p2

# Make mount point directories
imgbootpmnt=$(mktemp -d sdbootXXX)
imgrootfspmnt=$(mktemp -d sdrootfsXXX)

mount ${imgbootp} ${imgbootpmnt}
mount ${imgrootfsp} ${imgrootfspmnt}

# Rsync contents of the boot and rootfs partitions to the SD card
rsync -Hav --progress ${imgbootpmnt}/ ${bootpmnt}
rsync -Hav --progress ${imgrootfspmnt}/ ${rootfspmnt}

sync

umount ${imgbootp}
umount ${imgrootfsp}

rm -r ${imgbootpmnt}
rm -r ${imgrootfspmnt}

echo "--- Removing loop device"
kpartx -dv ${loopdevice}
losetup -d ${loopdevice}

umount ${bootp}
umount ${rootfsp}
rm -r ${bootpmnt}
rm -r ${rootfspmnt}

eject ${SD_CARD_DEV}

Manual SD Card Disk Layout

Partitioning the SD Card (fdisk)

Before partitioning the SD card, any partitions that have been mounted on the system must be unmounted. This can be done using the umount command.

umount /dev/sdb1

Once the SD card has been located, we can partition it for the Linux system (BOOT partition) and root filesystem (ROOTFS partition) using fdisk. fdisk must be run with root permissions (sudo) using the disk parent as the argument (do not use the parition number in the argument).

sudo fdisk /dev/sdb

From within the fdisk interface, we can view the parition table at any time using the "p" command. In this example, an 8GB SD card with a single FAT32 partition is being used and will be re-partitioned for snickerdoodle.

Command (m for help): p

Disk /dev/sdb: 7969 MB, 7969177600 bytes
255 heads, 63 sectors/track, 968 cylinders, total 15564800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            8192    15564799     7778304    b  W95 FAT32

BOOT Partition

First, a partition must be allocated for the Linux system binaries and files. This includes BOOT.bin (FSBL, bitstream, U-Boot), uEnv.txt, devicetree.dtb, and the Linux kernel uImage. The partition size for these files is recommended to be 128MB in size which translates to an additional 262144, 512 byte sectors.

Command (m for help): d
Selected partition 1

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-15564799, default 2048): <RETURN>
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-15564799, default 15564799): +262144

The default partition type for fdisk is Linux (type ID 83). The BOOT partition needs to be formatted as FAT32 (type ID "C"). Do do this, the "t" command is used:

Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

ROOTFS Partition

Second, a partition for the root filesystem must be created. This partition will be formatted as a Linux type using type ID 83. This is the default partition type.

Command (m for help): n 
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e extended
Select (default p): p
Partition number (1-4, default 2): <RETURN>
Using default value 2
First sector (264193-15564799, default 264193): <RETURN> Using default value 264193
Last sector, +sectors or +size{K,M,G} (264193-15564799, default 15564799): <RETURN>
Using default value 15564799

Before writing the parition table, you should verify the partition layout by printing it with the ’p’ command. In this example, an 8GB SD card has been partitioned with a 128MB FAT32 BOOT partition and the rest allocated for a Linux ROOTFS partition.

Command (m for help): p

Disk /dev/sdb: 7969 MB, 7969177600 bytes
255 heads, 63 sectors/track, 968 cylinders, total 15564800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Device Boot Start End Blocks Id System
/dev/sdb1            2048      264192      131072+   c  W95 FAT32 (LBA)
/dev/sdb2          264193    15564799     7650303+  83  Linux

Writing Parition Table

Once the partition table has been verified, the ’w’ command can be used to write the table to the disk:

Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.


Formatting Partitions

With a partitioned SD card, the partitions need to be formatted with the necessary filesystem type. For the BOOT partition, the filesystem type is VFAT. Formatting the BOOT partition can be done using the mkfs.vfat3. To format a FAT32 filesystem on /dev/sdb1 with a ’BOOT’ disk label, the following command can be used:

mkfs.vfat -n BOOT /dev/sdb1

The format for the ROOTFS partition can be done with mke2fs which will format a Linux partition with an ext2/ext3/ext4 filesystem. To format an ext4 filesystem on /dev/sdb2 with a block size of 1k (1024) and a ’ROOTFS’ disk label, the following command can be used:


If the formatting is successful, the following output with be written to the console (writing superblocks and filesystem accounting information can take some time depending on the size and speed of the SD card):

$ mke2fs -b 4096 -t ext4 -L ROOTFS /dev/sdb2
mke2fs 1.42.9 (4-Feb-2014)
Filesystem label=ROOTFS
OS type: Linux
Block size=4096 (log=0)
Fragment size=4096 (log=0)
Stride=0 blocks, Stripe width=0 blocks
478208 inodes, 7650300 blocks
382515 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=74973184
934 block groups
8192 blocks per group, 8192 fragments per group
512 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409, 663553,
    1024001, 1990657, 2809857, 5120001, 5971969
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

After the partitions have been properly formatted, the SD card must be ejected and re-connected before moving the Linux boot components and root filesystem contents to the disk.

eject /dev/sdb

Loading SD Card Images

Boot Partition Components

  • boot.bin (FSBL/U-Boot)
  • boot.script.img (system boot script)
  • devicetree.dtb (device tree blob)
  • uEnv.txt (U-Boot supplementary environment definition)
  • uImage (Linux kernel image)


Rootfs Partition

Root Filesystem