I've been fascinated for a while on the idea of building my own home network, however with little time and somewhat being stubborn on the specifics I've pushed it off until most of the pieces come to together. Nonetheless, I plan on documenting as much of the process as possible in hopes to keep a "log", as well as hopefully teach others as I learn. Probably impossible to teach something you know so little about, but you miss the shots you don't take, as they say.
Purpose of this bit is to construct an Alpine Linux-based dropbox running atop an SBC (Single-Board-Computer) to allow internal access into the network from anywhere (well, the ones I permit anyhow). For this, I've chosen:
- Odroid N2 : Device seemed perfect for the scenario. On AmeriDroid, I purchased the 4GB & 2GB models found here.
- 64GB Sandisk SdCard. Possibly won't need as much storage, however in the long term I'll be storing logs etc for long periods at a time, figured wouldn't hurt since its dirt cheap.
- KKSB Case. Made of Aluminum, seemed a nice touch and a protective casing. Will be added in the final build , although probably not needed for your own purposes.
- 12v/12a Power Supply . Apparently the offically recommended one, so I'll stick with it to avoid power supply issues.
- USB-UART Module Kit. We're gonna need to debug the u-boot startup along the way, cause yeah I have no clue what I'm doing / it wont print the boot process elsewhere but the Serial Console =).
Quite a large sum in the end, however, most I acquired directly from the AmeriDroid. You could purchase likely purchase it from HardKernel's official website (developers of the Odroid device set), however being in America, its not as cheap for me.
For my host machine, I'm utilizing Ubuntu 18.04. Although its not a specific and , honestly not required (pick your poison, I just prefer it since its simple). For the build and filesystem construction, please install make and u-boot-tools. I'll also be using fdisk, as trying to create partitions with Mac OS X was a pain, although would work fine in a Fusion/Parallels VM (tested).
To start, we'll be setting up our new sdCard to hold the boot media, such as the gzip'ed GNU/Linux Kernel, in addition to the Device Tree Blob, herein refered to as the DTB or dtb. Popping open fdisk, we'll be clearing any partitions from the device, and adding two additional entries, one in W32 FAT format (vFat), as well as standard a Linux partition (ext4/ext3/ext2, I'll be using ext4 for no particular reason).
Careful about the disk you're creating partitions for, ensure its actually your sdCard. Made that mistake and cleared + shredded a 4TB hard drive (yay)
$ sudo fdisk -l
- SNIP -
Device Boot Start End Sectors Size Id Type
/dev/sdd1 32768 124735487 124702720 59.5G 7 HPFS/NTFS/exFAT
- SNIP -
$ sudo fdisk /dev/sdd
Welcome to fdisk (util-linux 2.31.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): o
Created a new DOS disklabel with disk identifier 0x80819f47.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-124735487, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-124735487, default 124735487): +256M
Created a new partition 1 of type 'Linux' and of size 256 MiB.
Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): c
Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
$
In this bit, we've wiped the current partition table (originally NTFS/exFAT) as we'll be replacing it with a Windows 95 FAT32 Partition, which Odroid reads as a valid boot partition. We minimize its size all the way down to 256 megabytes, as we wont need much to be hosting its boot files (kernel, boot.ini, and dtb).
Next, we create the "root" filesystem in ext4 format. According to research, its the most "stable" compared to ext3 and ext2, as well as the default format for most Linux distros. Thusly, we'll be sticking with that.
$ sudo fdisk /dev/sdd
Welcome to fdisk (util-linux 2.31.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2):
First sector (526336-124735487, default 526336):
Last sector, +sectors or +size{K,M,G,T,P} (526336-124735487, default 124735487):
Created a new partition 2 of type 'Linux' and of size 59.2 GiB.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
$
Awesome! We should now have two partiotions, one of which will hold the boot directory / files, and another which will hold our actual filesystem / init. Now we have to create the actual "filesystem" formats using mkfs from u-boot tools. Without this, the partitions will not be mountable. We'll also be placing labels on them so as to avoid confusion.
$ sudo mkfs.vfat -n "BOOT" /dev/sdd1
mkfs.fat 4.1 (2017-01-24)
$ sudo mkfs.ext4 -l "rootfs" /dev/sdd2
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 15526144 4k blocks and 3883008 inodes
Filesystem UUID: c2a78ad2-e8f3-478b-9e9f-6d9b4f51a718
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424
Allocating group tables: done
Writing inode tables: done
Creating journal (65536 blocks): done
Writing superblocks and filesystem accounting information:
done
$
#
# Note : /dev/sdd1 & /dev/sdd2 correspond with their
# partition number entries + /dev/sdd (device) for the
# sd card, in case that confused anyone :).
#
Lovely. So we've built our actual filesystems, now to build the actual files we'll be dropping into their appropriate directories. I've setup my project layout like so : (thanks tree!)
.
├── downloads - Holds any files we download.
├── output - Output for any files. Saves clutter
└── sdmount - Where we'll be mounting our sdCard
├── boot
└── rootfs
5 directories, 0 files
We'll be attemping to first boot the kernel. To start, I'll be using the official Odroid N2 kernel from HardKernel. I'm not sure of the mainline kernel would work (I certainly have not attempted), so for this case, I'll stick with what I know for sure works. You can clone the current kernel by :
$ git clone --depth 1 https://github.com/hardkernel/linux.git -b odroidn2-4.9.y output/linux-kernel-odroidn2
$ sudo mount -o rw /dev/sdd1 sdmount/boot
$ sudo mount -o rw /dev/sdd2 sdmount/rootfs
Since it requires a specific kernel, I'll be using the recommended Linaro gLibc compiler (aarch64-linux-gnu-) from their official site.
$ wget https://releases.linaro.org/components/toolchain/binaries/6.3-2017.02/aarch64-linux-gnu/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz -O downloads/gcc-aarch64-linux-gnu.tar.xz 1>/dev/null 2>/dev/null
$ tar -xf downloads/gcc-aarch64-linux-gnu.tar.xz -C output/
Woot! and onto building the actual kernel :). I'll be using debugging print , as I want to observe any issues that may arise during the initialiation process, so that I may properly develop a solution.
$ cd output/linux-kernel-odroidn2
$ PATH=../gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin/:$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- odroidn2_defconfig
- snip -
#
# configuration written to .config
#
$ PATH=../gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin/:$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j50
#
# Note : I use 50 cause I want this stuff to run as fast
# as possible. Careful for you - you may not have alot of
# cores / memory
#
$ mkdir -p ~/dropbox/sdcard/boot/boot && cp arch/arm64/boot/Image.gz arch/arm64/boot/amlogic/meson64_odroidn2.dtb ~/dropbox/sdcard/boot/boot
Once that has completed, we're gonna then copy over our kernel imag,e as well as the DTB. We'll have to construct a boot.ini, which is the instructions u-boot utilitizes to start the kernel, and pass any arguments to the kernel which will initilize the system.
I've setup my boot.ini to follow the format of starting the boot device (/dev/Image) with kernel status prints using earlyprintk. Connect your UART cable to the debug interface (serial), and connect the other end to your USB-3.0 card reader. Then, using screen, type screen /dev/ttyUSB0 115200 8N1, which will connect to the serial console.
$ vi ~/dropbox/sdcard/boot/boot.ini
ODROIDN2-UBOOT-CONFIG
setenv bootargs "earlyprintk /dev/Image.gz console=ttyS0,115200n8"
setenv dtb_loadaddr "0x1000000"
setenv k_addr "0x1100000"
setenv loadaddr "0x1B00000"
setenv initrd_loadaddr "0x3700000"
fatload mmc ${devno}:1 ${k_addr} boot/Image.gz
fatload mmc ${devno}:1 ${dtb_loadaddr} boot/meson64_odroidn2.dtb
fdt addr ${dtb_loadaddr}
unzip ${k_addr} ${loadaddr}
booti ${loadaddr} - ${dtb_loadaddr}