├── LICENSE ├── README.md ├── images ├── bee42-logo.jpg └── bee42-workshop.jpg ├── part1-bootloader.md ├── part2-kernel.md ├── part3-root-filesystem.md └── part4-sd-card-image.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dieter Reuter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Workshop: 3 | # Building a 64bit Docker OS for the Raspberry Pi 3 4 | 5 | In this "short" workshop I'm going through all the steps to build a complete 64bit operating system for the Raspberry Pi 3. This 64bit HypriotOS is mainly focused on running Docker containers easily on this popular DIY and IoT device. 6 | 7 | You'll see that I'm using Docker heavily for each and every build step, because it really helps us a lot to run a local build with [Docker-for-Mac](https://docs.docker.com/docker-for-mac/) or later on the cloud build servers at [Travis CI](https://travis-ci.org). 8 | 9 | ![bee42-workshop.jpg](/images/bee42-workshop.jpg) 10 | 11 | This workshop is sponsored by [bee24 solutions](http://bee42.com) Follow @bee42solutions 12 | 13 | 14 | ### Background and Contents 15 | 16 | As you may already know, a complete Linux operating system consists of several important building blocks and I'd like to show you how to build all of these step by step. 17 | 18 | For this purpose I'm not going to reinvent the wheel and so I'll reuse all of the existing parts which are already published by the Raspberry Pi Organisation, by the Debian Linux project and will add some more glue code. 19 | 20 | At the end you should have learned how to build all the necessary parts and how to automatically create a finished SD card image which could be flashed on an empty SD card. Then boot your Raspberry Pi 3 with and in less than a minute you have a fully running Docker Engine on a Debian-based 64bit Linux OS. 21 | 22 | Here is a short overview of the contents of the workshop: 23 | 24 | * [Part 1: Bootloader](/part1-bootloader.md) 25 | 26 | * [Part 2: Kernel](/part2-kernel.md) 27 | 28 | * [Part 3: Root Filesystem](/part3-root-filesystem.md) 29 | 30 | * [Part 4: SD Card Image](/part4-sd-card-image.md) 31 | 32 | So, that's enough for explaining the background of this workshop. For more informations 33 | please follow along the details I'll publish on the coming tweets at Twitter and in the 34 | GitHub repos until all the parts of this workshop are finished and available as OpenSource. 35 | 36 | Please be aware that this OS is in a development phase and far from being perfect. 37 | So you are encouraged to help me with reporting issues and filing pull-requests to 38 | add features and fix bugs. 39 | 40 | 41 | ### Raspberry Pi 3 Model B 42 | 43 | **Specification** 44 | 45 | ![Raspi3-Image](https://upload.wikimedia.org/wikipedia/commons/e/e6/Raspberry-Pi-3-Flat-Top.jpg) 46 | 47 | Even more technical specs can be found at [Wikipedia](https://en.wikipedia.org/wiki/Raspberry_Pi) or in this detailed [MagPi article](https://www.raspberrypi.org/magpi/raspberry-pi-3-specs-benchmarks/). 48 | 49 | -- 50 | 51 | ![bee42-logo.jpg](/images/bee42-logo.jpg) 52 | 53 | -- 54 | MIT License 55 | 56 | Copyright (c) 2017 Dieter Reuter 57 | -------------------------------------------------------------------------------- /images/bee42-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DieterReuter/workshop-raspberrypi-64bit-os/878fd9bfba613bbdd77c91416077c694d204f987/images/bee42-logo.jpg -------------------------------------------------------------------------------- /images/bee42-workshop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DieterReuter/workshop-raspberrypi-64bit-os/878fd9bfba613bbdd77c91416077c694d204f987/images/bee42-workshop.jpg -------------------------------------------------------------------------------- /part1-bootloader.md: -------------------------------------------------------------------------------- 1 | 2 | # Part 1: Bootloader 3 | 4 | In order to know which essential files are needed to boot the Raspberry Pi from a SD card we have to dig a little bit deeper into the boot process itself. The boot process is almost the same for each and every Raspberry Pi model, so let's read this as a basic primer. 5 | 6 | 7 | ## Raspberry Pi Boot Process 8 | 9 | Booting a Raspberry Pi is a little bit different because the CPU is offline from the beginning and the SoC (system on a chip) starts the GPU first which initializes the important system components and controls or better starts the low level boot process. 10 | 11 | * **First Stage Bootloader** - 12 | The first stage bootloader is located in the ROM section of the SoC, so it is baked-in into the hardware chip. It mounts the FAT32 boot section/partition of the SD card in order to have access to load the necessary files like the second stage bootloader. 13 | 14 | * **Second Stage Bootloader** - 15 | The second stage bootloader will be loaded from the file "bootcode.bin" which contains the GPU code to start the GPU and loading the GPU firmware. So you can see that "bootcode.bin" contains just GPU specific code and will be provided as a closed-source binary blob. 16 | 17 | * **GPU Firmware** - 18 | The GPU firmware itself is loaded from the file "start.elf" and enables the GPU to load and run ARM specific user code for the CPU like our Linux kernel which we need to start our Linux operating system. 19 | 20 | * **User Code** - 21 | The user code will be run on the CPU and is therefore compiled for the specific ARM processor. Normally this is the Linux kernel which is compiled for ARMv6 or ARMv7 architecture for running Raspbian, but we're going to use a Linux kernel for ARMv8 (or ARM64) which is also known as the AARCH64 architecture. 22 | 23 | I'm just touching the basic parts here and if you're interested in all the details you can find the boot process explained in more detail at http://elinux.org/RPi_Software or read the latest documentation about the [Raspberry Pi Boot Modes](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/). 24 | 25 | 26 | ## 32bit or 64bit, Who knows? 27 | 28 | The bootloader software from the Raspberry Pi repo is exactly the same to use for 32 and 64bit systems. The hardware will be checked at boot time, so the bootloader knows the correct hardware SOC and if it's capable to run 64bit code or not. Then it tries to load the 64bit kernel only on RPi3. If there's no 64bit kernel it falls back to load a 32bit kernel and so on. Same thing works for ARMv8, ARMv7 and ARMv6 SOCs. 29 | 30 | For us this automatic detection is pretty cool, because it just magically works and gives us the flexibility to build a SD card with different kernel version that works on all Pi models from 1, 2, 3, Zero and Zero W. 31 | 32 | 33 | ## Minimum Boot Files 34 | 35 | As we learned about the boot process, we do have only a few requirements to successfully boot a Raspberry Pi from a SD card: 36 | 37 | * **FAT32 filesystem** - 38 | will be mounted later as "/boot" in Linux 39 | * **File "bootcode.bin"** - Second Stage Bootloader 40 | * **File "start.elf"** - GPU Firmware 41 | * **File "fixup.dat"** - (optional) used to configure the SDRAM partition between GPU and CPU 42 | 43 | And next the user code like the Linux kernel to bring our system to life. 44 | 45 | > These are really the minimum required bootfiles to boot a Raspberry Pi from SD card: 46 | 47 | > "bootcode.bin", "start.elf", "fixup.dat", "kernel.img" 48 | 49 | To be honest, we do need a few more files for starting and configuring the Linux kernel and to access the serial UART console. So I'm listing here the bare minimum bootfiles to really boot into our Linux kernel and so we can see the kernel logs appear on the serial UART console. 50 | ``` 51 | $ ls -al 52 | total 15284 53 | drwxr-xr-x 2 root root 16384 Mar 3 11:12 . 54 | drwxr-xr-x 21 root root 4096 Jul 3 2014 .. 55 | -rwxr-xr-x 1 root root 17253 Mar 1 17:42 bcm2710-rpi-3-b.dtb 56 | -rwxr-xr-x 1 root root 50268 Mar 1 16:58 bootcode.bin 57 | -rwxr-xr-x 1 root root 215 Mar 1 18:14 cmdline.txt 58 | -rwxr-xr-x 1 root root 50 Mar 3 11:12 config.txt 59 | -rwxr-xr-x 1 root root 6640 Mar 1 16:58 fixup.dat 60 | -rwxr-xr-x 1 root root 12704256 Mar 1 17:42 kernel8.img 61 | -rwxr-xr-x 1 root root 2841412 Mar 1 16:58 start.elf 62 | ``` 63 | 64 | 65 | ## Where to get the bootloader files? 66 | 67 | As I already mentioned before, these bootloader files are provided as closed-source binary blobs directly from the Raspberry Pi Foundation and can be downloaded from the "boot" section/folder of the Raspberry Pi Firmware repo [raspberrypi/firmware on GitHub](https://github.com/raspberrypi/firmware/tree/master/boot). 68 | 69 | 70 | ## Let's build a bootloader package 71 | 72 | Now it's time to build our first component, the "rpi-bootloader" which contains just the bootfiles for the Raspberry Pi. And for easy use we're just going to create a tarball with the essential bootfiles. 73 | > As these bootfiles are not specific to a Raspberry Pi 3 only, we could possibly reuse this package later for all the other Raspberry Pi models as well. 74 | 75 | I've already prepared a GitHub repo to create a tarball https://github.com/dieterreuter/rpi-bootloader. 76 | 77 | 78 | ### How the build process works 79 | 80 | The build process uses Docker Compose to build a Docker Image first with a complete build environment based upon Debian/Jessie. So you can see, this build always run in a well defined environment. It's running in an isolated Linux with Debian/Jessie inside of a Docker container. In this case we don't have to install anything (except Docker itself or on macOS Docker-for-Mac) on our host machine. 81 | 82 | As you can see, I'm using the command `docker-compose build` to build the Docker Image and later on I'm issuing a single build run with the command `docker-compose run builder`. That's all. 83 | ``` 84 | $ cat build.sh 85 | #!/bin/bash 86 | set -e 87 | 88 | docker-compose build 89 | docker-compose run builder 90 | ``` 91 | 92 | For easier usage I created a script "build.sh" with these two commands, so we can just invoke a new build with a single command only. 93 | ``` 94 | $ ./build.sh 95 | ``` 96 | 97 | The build results can be found in a sub-folder `./builds/`, for each new build the script `build-tarball.sh` is creating a new build folder with an individual version based upon the date+time of the current build. So we can run subsequent builds and keep all the old build artefacts. 98 | ``` 99 | $ tree builds/ 100 | builds/ 101 | └── 20170303-121340 102 | ├── rpi-bootloader.tar.gz 103 | └── rpi-bootloader.tar.gz.sha256 104 | 105 | 1 directory, 2 files 106 | ``` 107 | 108 | 109 | ### Create a Travis CI build job 110 | 111 | Most of the times it is easier and more reliable to use a CI (continous integration) system to run the build process on a cloud server, so I'm going to use [Travis CI](https://travis-ci.org). 112 | 113 | I just created the necessary Travis configuration file `.travis.yml` with some special settings. 114 | ``` 115 | $ cat .travis.yml 116 | sudo: required 117 | services: 118 | - docker 119 | language: bash 120 | script: 121 | - ./travis-build.sh 122 | after_success: 123 | - ls -al builds/$BUILD_NR/* 124 | branches: 125 | only: 126 | - master 127 | except: 128 | - /^v\d.*$/ 129 | ``` 130 | 131 | With the help of an extra Travis build script `travis-build.sh` I'm now able to upload the build artefacts of every successful build as a new GitHub release at https://github.com/DieterReuter/rpi-bootloader/releases. This makes it very easy to consume these build artefacts later in another build process and I do have all the complete and detailed build logs available for future reference. 132 | 133 | 134 | ## Recap 135 | 136 | We talked about the Raspberry Pi boot process in detail and have shown the minimum required bootfiles. 137 | 138 | Then we've built a GitHub repo with a complete automated build process to fetch all files from the original Raspberry Pi Firmware repo and then building a versioned tarball. We can run the build process for development locally on macOS with the help of [Docker-for-Mac](https://docs.docker.com/docker-for-mac/) and later on the cloud build servers at [Travis CI](https://travis-ci.org). 139 | 140 | At the end we can just use the produced tarball "rpi-bootloader.tar.gz" in order to copy all the bootfiles to a SD card to get the latest version. 141 | 142 | ``` 143 | $ tar vtf builds/20170303-121340/rpi-bootloader.tar.gz 144 | -rw-r--r-- 0 root root 1494 Mar 3 13:14 boot/LICENCE.broadcom 145 | -rw-r--r-- 0 root root 50268 Mar 3 13:14 boot/bootcode.bin 146 | -rw-r--r-- 0 root root 6646 Mar 3 13:14 boot/fixup.dat 147 | -rw-r--r-- 0 root root 2558 Mar 3 13:14 boot/fixup_cd.dat 148 | -rw-r--r-- 0 root root 9777 Mar 3 13:14 boot/fixup_db.dat 149 | -rw-r--r-- 0 root root 9775 Mar 3 13:14 boot/fixup_x.dat 150 | -rw-r--r-- 0 root root 2846692 Mar 3 13:14 boot/start.elf 151 | -rw-r--r-- 0 root root 654980 Mar 3 13:14 boot/start_cd.elf 152 | -rw-r--r-- 0 root root 4983140 Mar 3 13:14 boot/start_db.elf 153 | -rw-r--r-- 0 root root 3929604 Mar 3 13:14 boot/start_x.elf 154 | ``` 155 | 156 | To create a bootable SD card we now have to format a SD card with FAT32 and have to copy all the files from the "/boot" folder into the root directory of the SD card. But as we don't have any meaningful user code embedded yet, like "kernel8.img", we won't see anything on an attached HDMI monitor nor on the serial UART console. This will be covered in detail in [Part 2 - Kernel](/part2-kernel.md). 157 | 158 | -- 159 | 160 | ![bee42-logo.jpg](/images/bee42-logo.jpg) 161 | 162 | -- 163 | MIT License 164 | 165 | Copyright (c) 2017 Dieter Reuter 166 | -------------------------------------------------------------------------------- /part2-kernel.md: -------------------------------------------------------------------------------- 1 | 2 | # Part 2: Kernel 3 | 4 | ## Using the Linux kernel 5 | 6 | At the end of the boot process the bootloader will automatically detect the CPU model and tries to load and run a pre-defined Linux kernel. As the first Raspberry Pi uses an ARMv6 CPU and later on with the Raspberry Pi 2 an ARMv7 CPU, the bootloader can load both different kernels. Here are the default filenames we could use for these different kernel versions: 7 | 8 | * **kernel.img** - for ARMv6 (Raspberry 1, Zero, Zero W) 9 | * **kernel7.img** - for ARMv7 (Raspberry 2, 3 in 32bit mode) 10 | * **kernel8.img** - for ARMv8,ARM64,AARCH64 (Raspberry 3 in 64bit mode) 11 | 12 | As we're going right into a 64bit Linux system, we're using "kernel8.img" as our user code to be started directly through the bootloader. To be honest there are some more additional configuration files which will be needed to start and configure our Linux kernel in the right way. 13 | 14 | * **kernel8.img** - the 64bit kernel for the Raspberry Pi 3 15 | * **bcm2710-rpi-3-b.dtb** - device tree binary Linux kernel configuration 16 | * **config.txt** - configuration file read by the bootloader 17 | * **cmdline.txt** - kernel commandline parameters 18 | 19 | Now we do have these minimal bootfiles which consists on the bootloader itself, the Linux kernel as user code and some configuration files. As soon as we put these on a SD card with FAT32 format, our Raspberry Pi 3 can be booted from and will show detailed kernel logs while booting on the serial UART console. 20 | ``` 21 | $ ls -al 22 | total 15284 23 | drwxr-xr-x 2 root root 16384 Mar 3 11:12 . 24 | drwxr-xr-x 21 root root 4096 Jul 3 2014 .. 25 | -rwxr-xr-x 1 root root 17253 Mar 1 17:42 bcm2710-rpi-3-b.dtb 26 | -rwxr-xr-x 1 root root 50268 Mar 1 16:58 bootcode.bin 27 | -rwxr-xr-x 1 root root 215 Mar 1 18:14 cmdline.txt 28 | -rwxr-xr-x 1 root root 50 Mar 3 11:12 config.txt 29 | -rwxr-xr-x 1 root root 6640 Mar 1 16:58 fixup.dat 30 | -rwxr-xr-x 1 root root 12704256 Mar 1 17:42 kernel8.img 31 | -rwxr-xr-x 1 root root 2841412 Mar 1 16:58 start.elf 32 | ``` 33 | 34 | One important part to use the serial UART console is the configuration of `enable_uart=1` in "config.txt". 35 | ``` 36 | $ cat config.txt 37 | # enable UART console on GPIO pins 38 | enable_uart=1 39 | ``` 40 | 41 | And there are some more parameters to set in the kernel commandline like `console=tty1`, `console=ttyAMA0,115200` and `kgdboc=ttyAMA0,115200`. 42 | ``` 43 | $ cat cmdline.txt 44 | +dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 cgroup_enable=cpuset cgroup_enable=memory swapaccount=1 elevator=deadline fsck.repair=yes rootwait console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 45 | ``` 46 | 47 | Here are the kernel logs (seen on serial UART console) of a boot attempt with such a 64bit Linux kernel but without having a root filesystem available on the SD card. 48 | ``` 49 | [ 0.000000] Booting Linux on physical CPU 0x0 50 | [ 0.000000] Linux version 4.9.13-bee42-v8 (root@1aca9db9a114) (gcc version 6.2.1 20161016 (Linaro GCC 6.2-2016.11) ) #1 SMP PREEMPT Wed Mar 1 17:38:31 UTC 2017 51 | [ 0.000000] Boot CPU: AArch64 Processor [410fd034] 52 | [ 0.000000] efi: Getting EFI parameters from FDT: 53 | [ 0.000000] efi: UEFI not found. 54 | [ 0.000000] cma: Reserved 8 MiB at 0x0000000007400000 55 | [ 0.000000] percpu: Embedded 22 pages/cpu @fffffffc07f7d000 s52632 r8192 d29288 u90112 56 | [ 0.000000] Detected VIPT I-cache on CPU0 57 | [ 0.000000] CPU features: enabling workaround for ARM erratum 845719 58 | [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32256 59 | [ 0.000000] Kernel command line: 8250.nr_uarts=1 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708_fb.fbswap=1 vc_mem.mem_base=0xec00000 vc_mem.mem_size=0x10000000 +dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 cgroup_enable=cpuset cgroup_enable=memory swapaccount=1 elevator=deadline fsck.repair=yes rootwait console=ttyS0,115200 kgdboc=ttyS0,115200 60 | [ 0.000000] PID hash table entries: 512 (order: 0, 4096 bytes) 61 | [ 0.000000] Dentry cache hash table entries: 16384 (order: 5, 131072 bytes) 62 | [ 0.000000] Inode-cache hash table entries: 8192 (order: 4, 65536 bytes) 63 | [ 0.000000] Memory: 92532K/131072K available (6588K kernel code, 758K rwdata, 2384K rodata, 2624K init, 830K bss, 30348K reserved, 8192K cma-reserved) 64 | [ 0.000000] Virtual kernel memory layout: 65 | [ 0.000000] modules : 0xffffff8000000000 - 0xffffff8008000000 ( 128 MB) 66 | [ 0.000000] vmalloc : 0xffffff8008000000 - 0xffffffbebfff0000 ( 250 GB) 67 | [ 0.000000] .text : 0xffffff99ee680000 - 0xffffff99eecf0000 ( 6592 KB) 68 | [ 0.000000] .rodata : 0xffffff99eecf0000 - 0xffffff99eef50000 ( 2432 KB) 69 | [ 0.000000] .init : 0xffffff99eef50000 - 0xffffff99ef1e0000 ( 2624 KB) 70 | [ 0.000000] .data : 0xffffff99ef1e0000 - 0xffffff99ef29da00 ( 759 KB) 71 | [ 0.000000] .bss : 0xffffff99ef29da00 - 0xffffff99ef36d214 ( 831 KB) 72 | [ 0.000000] fixed : 0xffffffbefe7fd000 - 0xffffffbefec00000 ( 4108 KB) 73 | [ 0.000000] PCI I/O : 0xffffffbefee00000 - 0xffffffbeffe00000 ( 16 MB) 74 | [ 0.000000] vmemmap : 0xffffffbf00000000 - 0xffffffc000000000 ( 4 GB maximum) 75 | [ 0.000000] 0xffffffbff0000000 - 0xffffffbff0200000 ( 2 MB actual) 76 | [ 0.000000] memory : 0xfffffffc00000000 - 0xfffffffc08000000 ( 128 MB) 77 | [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1 78 | [ 0.000000] Preemptible hierarchical RCU implementation. 79 | [ 0.000000] Build-time adjustment of leaf fanout to 64. 80 | [ 0.000000] NR_IRQS:64 nr_irqs:64 0 81 | [ 0.000000] Failed to get local register map. FIQ is disabled for cpus > 1 82 | [ 0.000000] arm_arch_timer: Architected cp15 timer(s) running at 19.20MHz (phys). 83 | [ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x46d987e47, max_idle_ns: 440795202767 ns 84 | [ 0.000005] sched_clock: 56 bits at 19MHz, resolution 52ns, wraps every 4398046511078ns 85 | [ 0.000229] Console: colour dummy device 80x25 86 | [ 0.001448] console [tty1] enabled 87 | [ 0.001494] Calibrating delay loop (skipped), value calculated using timer frequency.. 38.40 BogoMIPS (lpj=19200) 88 | [ 0.001557] pid_max: default: 32768 minimum: 301 89 | [ 0.001879] Mount-cache hash table entries: 512 (order: 0, 4096 bytes) 90 | [ 0.001936] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes) 91 | [ 0.003015] ftrace: allocating 22746 entries in 89 pages 92 | [ 0.061760] ASID allocator initialised with 65536 entries 93 | [ 0.069681] EFI services will not be available. 94 | [ 0.078673] Detected VIPT I-cache on CPU1 95 | [ 0.078736] CPU1: Booted secondary processor [410fd034] 96 | [ 0.085780] Detected VIPT I-cache on CPU2 97 | [ 0.085825] CPU2: Booted secondary processor [410fd034] 98 | [ 0.092897] Detected VIPT I-cache on CPU3 99 | [ 0.092939] CPU3: Booted secondary processor [410fd034] 100 | [ 0.093043] Brought up 4 CPUs 101 | [ 0.093235] SMP: Total of 4 processors activated. 102 | [ 0.093274] CPU features: detected feature: 32-bit EL0 Support 103 | [ 0.093375] CPU: All CPU(s) started at EL2 104 | [ 0.093436] alternatives: patching kernel code 105 | [ 0.094492] devtmpfs: initialized 106 | [ 0.111145] DMI not present or invalid. 107 | [ 0.111535] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns 108 | [ 0.111608] futex hash table entries: 1024 (order: 5, 131072 bytes) 109 | [ 0.112284] pinctrl core: initialized pinctrl subsystem 110 | [ 0.113030] NET: Registered protocol family 16 111 | [ 0.124301] cpuidle: using governor menu 112 | [ 0.124751] vdso: 2 pages (1 code @ ffffff99eecf7000, 1 data @ ffffff99ef1e4000) 113 | [ 0.124819] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers. 114 | [ 0.126863] DMA: preallocated 256 KiB pool for atomic allocations 115 | [ 0.126996] Serial: AMBA PL011 UART driver 116 | [ 0.131843] bcm2835-mbox 3f00b880.mailbox: mailbox enabled 117 | [ 0.132710] uart-pl011 3f201000.serial: could not find pctldev for node /soc/gpio@7e200000/uart0_pins, deferring probe 118 | [ 0.185768] HugeTLB registered 2 MB page size, pre-allocated 0 pages 119 | [ 0.186779] bcm2835-dma 3f007000.dma: DMA legacy API manager at ffffff800804b000, dmachans=0x1 120 | [ 0.189271] SCSI subsystem initialized 121 | [ 0.189495] usbcore: registered new interface driver usbfs 122 | [ 0.189625] usbcore: registered new interface driver hub 123 | [ 0.189792] usbcore: registered new device driver usb 124 | [ 0.190077] dmi: Firmware registration failed. 125 | [ 0.191243] raspberrypi-firmware soc:firmware: Attached to firmware from 2017-02-26 20:30 126 | [ 0.192990] clocksource: Switched to clocksource arch_sys_counter 127 | [ 0.268406] VFS: Disk quotas dquot_6.6.0 128 | [ 0.268537] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes) 129 | [ 0.268826] FS-Cache: Loaded 130 | [ 0.269259] CacheFiles: Loaded 131 | [ 0.284203] NET: Registered protocol family 2 132 | [ 0.285250] TCP established hash table entries: 1024 (order: 1, 8192 bytes) 133 | [ 0.285321] TCP bind hash table entries: 1024 (order: 2, 16384 bytes) 134 | [ 0.285390] TCP: Hash tables configured (established 1024 bind 1024) 135 | [ 0.285523] UDP hash table entries: 256 (order: 1, 8192 bytes) 136 | [ 0.285583] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes) 137 | [ 0.285905] NET: Registered protocol family 1 138 | [ 0.286524] RPC: Registered named UNIX socket transport module. 139 | [ 0.286561] RPC: Registered udp transport module. 140 | [ 0.286592] RPC: Registered tcp transport module. 141 | [ 0.286622] RPC: Registered tcp NFSv4.1 backchannel transport module. 142 | [ 0.287909] hw perfevents: enabled with armv8_pmuv3 PMU driver, 7 counters available 143 | [ 0.290869] workingset: timestamp_bits=46 max_order=15 bucket_order=0 144 | [ 0.312215] FS-Cache: Netfs 'nfs' registered for caching 145 | [ 0.313373] NFS: Registering the id_resolver key type 146 | [ 0.313442] Key type id_resolver registered 147 | [ 0.313477] Key type id_legacy registered 148 | [ 0.316468] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251) 149 | [ 0.316691] io scheduler noop registered 150 | [ 0.316729] io scheduler deadline registered (default) 151 | [ 0.316813] io scheduler cfq registered 152 | [ 0.322871] BCM2708FB: allocated DMA memory c7450000 153 | [ 0.322946] BCM2708FB: allocated DMA channel 0 @ ffffff800804b000 154 | [ 0.329911] Console: switching to colour frame buffer device 82x26 155 | [ 0.334635] Serial: 8250/16550 driver, 1 ports, IRQ sharing enabled 156 | [ 0.337232] console [ttyS0] disabled 157 | [ 0.338686] 3f215040.serial: ttyS0 at MMIO 0x0 (irq = 61, base_baud = 31224999) is a 16550 158 | [ 1.028053] console [ttyS0] enabled 159 | [ 1.033775] KGDB: Registered I/O driver kgdboc 160 | [ 1.045837] bcm2835-rng 3f104000.rng: hwrng registered 161 | [ 1.052882] Unable to detect cache hierarchy from DT for CPU 0 162 | [ 1.079034] brd: module loaded 163 | [ 1.096254] loop: module loaded 164 | [ 1.100870] Loading iSCSI transport class v2.0-870. 165 | [ 1.107931] usbcore: registered new interface driver smsc95xx 166 | [ 1.115233] dwc_otg: version 3.00a 10-AUG-2012 (platform bus) 167 | [ 1.348566] Core Release: 2.80a 168 | [ 1.353150] Setting default values for core params 169 | [ 1.359424] Finished setting default values for core params 170 | [ 1.566921] Using Buffer DMA mode 171 | [ 1.571695] Periodic Transfer Interrupt Enhancement - disabled 172 | [ 1.579074] Multiprocessor Interrupt Enhancement - disabled 173 | [ 1.586210] OTG VER PARAM: 0, OTG VER FLAG: 0 174 | [ 1.592098] Dedicated Tx FIFOs mode 175 | [ 1.597506] WARN::dwc_otg_hcd_init:1053: FIQ DMA bounce buffers: virt = 0x08111000 dma = 0xc7444000 len=9024 176 | [ 1.610400] FIQ FSM acceleration enabled for : 177 | [ 1.610400] Non-periodic Split Transactions 178 | [ 1.610400] Periodic Split Transactions 179 | [ 1.610400] High-Speed Isochronous Endpoints 180 | [ 1.610400] Interrupt/Control Split Transaction hack enabled 181 | [ 1.640038] WARN::hcd_init_fiq:486: MPHI regs_base at 0x080fa000 182 | [ 1.647629] dwc_otg 3f980000.usb: DWC OTG Controller 183 | [ 1.654128] dwc_otg 3f980000.usb: new USB bus registered, assigned bus number 1 184 | [ 1.663064] dwc_otg 3f980000.usb: irq 15, io mem 0x00000000 185 | [ 1.670198] Init: Port Power? op_state=1 186 | [ 1.675593] Init: Power Port (0) 187 | [ 1.680489] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002 188 | [ 1.688830] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 189 | [ 1.697611] usb usb1: Product: DWC OTG Controller 190 | [ 1.703805] usb usb1: Manufacturer: Linux 4.9.13-bee42-v8 dwc_otg_hcd 191 | [ 1.711787] usb usb1: SerialNumber: 3f980000.usb 192 | [ 1.718827] hub 1-0:1.0: USB hub found 193 | [ 1.724060] hub 1-0:1.0: 1 port detected 194 | [ 1.730839] usbcore: registered new interface driver usb-storage 195 | [ 1.738653] mousedev: PS/2 mouse device common for all mice 196 | [ 1.746937] bcm2835-wdt 3f100000.watchdog: Broadcom BCM2835 watchdog timer 197 | [ 1.755655] bcm2835-cpufreq: min=600000 max=1200000 198 | [ 1.762551] sdhci: Secure Digital Host Controller Interface driver 199 | [ 1.770269] sdhci: Copyright(c) Pierre Ossman 200 | [ 1.776641] sdhost: log_buf @ ffffff800811b000 (c7447000) 201 | [ 1.830029] mmc0: sdhost-bcm2835 loaded - DMA enabled (>1) 202 | [ 1.859487] mmc-bcm2835 3f300000.mmc: mmc_debug:0 mmc_debug2:0 203 | [ 1.867014] mmc-bcm2835 3f300000.mmc: DMA channel allocated 204 | [ 1.898170] sdhci-pltfm: SDHCI platform and OF driver helper 205 | [ 1.906804] ledtrig-cpu: registered to indicate activity on CPUs 206 | [ 1.914506] hidraw: raw HID events driver (C) Jiri Kosina 207 | [ 1.921676] usbcore: registered new interface driver usbhid 208 | [ 1.928801] usbhid: USB HID core driver 209 | [ 1.934435] Initializing XFRM netlink socket 210 | [ 1.940234] NET: Registered protocol family 17 211 | [ 1.941315] Indeed it is in host mode hprt0 = 00021501 212 | [ 1.952802] mmc0: host does not support reading read-only switch, assuming write-enable 213 | [ 1.952957] Key type dns_resolver registered 214 | [ 1.963780] Registered cp15_barrier emulation handler 215 | [ 1.963807] Registered setend emulation handler 216 | [ 1.964921] registered taskstats version 1 217 | [ 1.972958] 3f201000.serial: ttyAMA0 at MMIO 0x3f201000 (irq = 72, base_baud = 0) is a PL011 rev2 218 | [ 1.973510] of_cfs_init 219 | [ 1.973712] of_cfs_init: OK 220 | [ 1.976953] mmc1: queuing unknown CIS tuple 0x80 (2 bytes) 221 | [ 1.983313] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) 222 | [ 1.999764] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) 223 | [ 2.028960] mmc1: queuing unknown CIS tuple 0x80 (7 bytes) 224 | [ 2.029346] Waiting for root device /dev/mmcblk0p2... 225 | [ 2.042281] mmc0: new high speed SDHC card at address aaaa 226 | [ 2.050102] mmcblk0: mmc0:aaaa SU16G 14.8 GiB 227 | [ 2.057653] mmcblk0: p1 228 | [ 2.069660] random: fast init done 229 | [ 2.105028] usb 1-1: new high-speed USB device number 2 using dwc_otg 230 | [ 2.113023] Indeed it is in host mode hprt0 = 00001101 231 | [ 2.132302] VFS: Cannot open root device "mmcblk0p2" or unknown-block(179,2): error -6 232 | [ 2.142782] Please append a correct "root=" boot option; here are the available partitions: 233 | [ 2.153872] 0100 4096 ram0 [ 2.157614] (driver?) 234 | [ 2.161381] 0101 4096 ram1 [ 2.165121] (driver?) 235 | [ 2.168816] 0102 4096 ram2 [ 2.172548] (driver?) 236 | [ 2.176165] 0103 4096 ram3 [ 2.179898] (driver?) 237 | [ 2.183500] 0104 4096 ram4 [ 2.187232] (driver?) 238 | [ 2.190834] 0105 4096 ram5 [ 2.194567] (driver?) 239 | [ 2.198135] 0106 4096 ram6 [ 2.201883] (driver?) 240 | [ 2.205474] 0107 4096 ram7 [ 2.209205] (driver?) 241 | [ 2.212793] 0108 4096 ram8 [ 2.216538] (driver?) 242 | [ 2.220130] 0109 4096 ram9 [ 2.223877] (driver?) 243 | [ 2.227446] 010a 4096 ram10 [ 2.231264] (driver?) 244 | [ 2.234793] 010b 4096 ram11 [ 2.238614] (driver?) 245 | [ 2.242099] 010c 4096 ram12 [ 2.245926] (driver?) 246 | [ 2.249406] 010d 4096 ram13 [ 2.253227] (driver?) 247 | [ 2.256667] 010e 4096 ram14 [ 2.260488] (driver?) 248 | [ 2.263872] 010f 4096 ram15 [ 2.267692] (driver?) 249 | [ 2.271042] b300 15558144 mmcblk0 [ 2.275044] driver: mmcblk 250 | [ 2.278801] b301 65536 mmcblk0p1 00000000-01[ 2.284164] 251 | [ 2.286557] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2) 252 | ``` 253 | 254 | We can see the kernel is starting in 64bit mode using a `AArch64 Processor` 255 | ``` 256 | [ 0.000000] Booting Linux on physical CPU 0x0 257 | [ 0.000000] Linux version 4.9.13-bee42-v8 (root@1aca9db9a114) (gcc version 6.2.1 20161016 (Linaro GCC 6.2-2016.11) ) #1 SMP PREEMPT Wed Mar 1 17:38:31 UTC 2017 258 | [ 0.000000] Boot CPU: AArch64 Processor [410fd034] 259 | ``` 260 | 261 | and is initializing all four available CPU cores 262 | ``` 263 | [ 0.093043] Brought up 4 CPUs 264 | [ 0.093235] SMP: Total of 4 processors activated. 265 | ``` 266 | 267 | but finally it ends up in a kernel panic because of the missing root filesystem. 268 | ``` 269 | [ 2.029346] Waiting for root device /dev/mmcblk0p2... 270 | ... 271 | [ 2.132302] VFS: Cannot open root device "mmcblk0p2" or unknown-block(179,2): error -6 272 | ... 273 | [ 2.286557] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2) 274 | ``` 275 | 276 | So, this was just for demonstrating the boot process until the Linux kernel will be loaded and started correctly. 277 | 278 | 279 | ## Building the Linux kernel 280 | 281 | But as you already guessed we have to build this 64bit Linux kernel first. And this will take some time to be explained and to run the kernel build itself. 282 | 283 | Luckily the Raspberry Pi Foundation provides a GitHub repo https://github.com/raspberrypi/linux with all the Linux kernel sources, and there is also a branch "rpi-4.9.y" which supports building a 64bit kernel. OK, this branch doesn't have a proper kernel configuration which is already optimized for Docker containers - but this part was just easy for me to fix. 284 | 285 | So I've already prepared a GitHub repo https://github.com/dieterreuter/rpi64-kernel to create a true 64bit Linux kernel for the Raspberry Pi 3. And of course with a Docker-optimized kernel configuration, where I have enable absolutely all necessary and important kernel modules and settings which helps to run Linux containers in an optimal way. 286 | 287 | The build process itself uses Docker Compose to build a Docker Image first with a complete build environment based upon Debian/Jessie. So you can see, this build always run in a well defined environment. It's running in an isolated Linux with Debian/Jessie inside of a Docker container. In this case we don't have to install anything (except Docker itself or on macOS Docker-for-Mac) on our host machine. 288 | 289 | As you can see, I'm using the command `docker-compose build` to build the Docker Image and later on I'm issuing a single build run with the command `docker-compose run builder`. And as a build parameter I can define a specific kernel default configuration file with `DEFCONFIG=docker_rpi3_defconfig`. That's all. 290 | ``` 291 | $ cat build.sh 292 | #!/bin/bash 293 | set -e 294 | 295 | export DEFCONFIG=docker_rpi3_defconfig 296 | docker-compose build 297 | docker-compose run builder 298 | ``` 299 | 300 | For easier usage I created a script "build.sh" with these commands, so we can just invoke a new build with a single command only. 301 | ``` 302 | $ ./build.sh 303 | ``` 304 | 305 | The build results can be found in a sub-folder `./builds/`, for each new build the script `build-kernel.sh` is creating a new build folder with an individual version based upon the date+time of the current build. So we can run subsequent builds and keep all the old build artefacts. 306 | ``` 307 | $ tree builds 308 | builds 309 | └── 20170303-152804 310 | ├── 4.9.13-bee42-v8.config 311 | ├── 4.9.13-bee42-v8.tar.gz 312 | ├── 4.9.13-bee42-v8.tar.gz.sha256 313 | ├── bootfiles.tar.gz 314 | └── bootfiles.tar.gz.sha256 315 | 316 | 1 directory, 5 files 317 | ``` 318 | ``` 319 | $ ls -al ./builds/20170303-152804/ 320 | -rw-r--r-- 1 dieter staff 140641 Mar 3 16:28 4.9.13-bee42-v8.config 321 | -rw-r--r-- 1 dieter staff 21863866 Mar 3 16:40 4.9.13-bee42-v8.tar.gz 322 | -rw-r--r-- 1 dieter staff 89 Mar 3 16:40 4.9.13-bee42-v8.tar.gz.sha256 323 | -rw-r--r-- 1 dieter staff 5092332 Mar 3 16:40 bootfiles.tar.gz 324 | -rw-r--r-- 1 dieter staff 83 Mar 3 16:40 bootfiles.tar.gz.sha256 325 | ``` 326 | 327 | From the build script `build-kernel.sh` we'll get a couple of build artefacts. In "bootfiles.tar.gz" are all the files which have to be placed in the "/boot" folder on the FAT32 partition. These are namely the 64bit Linux kernel "kernel8.img", the device tree binary Linux kernel configuration file "bcm2710-rpi-3-b.dtb" and the kernel overlay files in a folder called "overlays/". 328 | ``` 329 | $ tar vtf builds/20170303-152804/bootfiles.tar.gz 330 | -rw-r--r-- 0 root root 12704256 Mar 3 16:40 ./kernel8.img 331 | drwxr-xr-x 0 root root 0 Mar 3 16:40 ./overlays/ 332 | ... 333 | -rw-r--r-- 0 root root 17714 Mar 3 16:40 ./bcm2710-rpi-3-b.dtb 334 | ``` 335 | 336 | But more important is the file "4.9.13-bee42-v8.tar.gz". Here you'll find all kernel files we really need to install on "/boot" and in the root filesystem like "/lib/firmware" and the kernel modules "/lib/modules/4.9.13-bee42-v8/". 337 | ``` 338 | $ tar vtf builds/20170303-152804/4.9.13-bee42-v8.tar.gz 339 | drwxr-xr-x 0 root root 0 Mar 3 16:40 ./lib/modules/4.9.13-bee42-v8/ 340 | ... 341 | drwxr-xr-x 0 root root 0 Mar 3 16:40 ./lib/firmware/ 342 | ... 343 | drwxr-xr-x 0 root root 0 Mar 3 16:40 ./boot/ 344 | -rw-r--r-- 0 root root 12704256 Mar 3 16:40 ./boot/kernel8.img 345 | drwxr-xr-x 0 root root 0 Mar 3 16:40 ./boot/overlays/ 346 | ... 347 | -rw-r--r-- 0 root root 17714 Mar 3 16:40 ./boot/bcm2710-rpi-3-b.dtb 348 | ``` 349 | 350 | And if you're interested in the generated and used kernel configuration file, this can be found in "4.9.13-bee42-v8.config" as a build artefact. 351 | 352 | 353 | ### Create a Travis CI build job 354 | 355 | Most of the times it is easier and more reliable to use a CI (continous integration) system to run the build process on a cloud server, so I'm going to use [Travis CI](https://travis-ci.org). 356 | 357 | I just created the necessary Travis configuration file `.travis.yml` with some special settings. 358 | ``` 359 | $ cat .travis.yml 360 | sudo: required 361 | services: 362 | - docker 363 | language: bash 364 | script: 365 | - ./travis-build.sh 366 | after_success: 367 | - ls -al builds/$BUILD_NR/* 368 | branches: 369 | only: 370 | - master 371 | except: 372 | - /^v\d.*$/ 373 | ``` 374 | 375 | With the help of an extra Travis build script `travis-build.sh` I'm now able to upload the build artefacts of every successful build as a new GitHub release at https://github.com/DieterReuter/rpi64-kernel/releases. This makes it very easy to consume these build artefacts later in another build process and I do have all the complete and detailed build logs available for future reference. 376 | 377 | 378 | ## Recap 379 | 380 | First we discussed how the Linux kernel will be used in the boot process and which necessary files we need to install on the "/boot" section of the FAT32 partiton on the SD card. Then we were able to boot a 64bit Linux kernel successfully on a Raspberry Pi 3 and seen the kernel boot logs appear on the serial UART console. 381 | 382 | With the help of a newly created GitHub repo we're now able to compile and package all necessary Linux kernel files in tarballs, so we could copy them over onto a SD card. 383 | 384 | From the boot attempt we know that the Linux kernel ends up in a "kernel panic", because we didn't provide a valid root filesystem on our SD card. So for the next part we'll covering how to create and use such a root filesystem 385 | in [Part 3 - Root filesystem](/part3-root-filesystem.md). 386 | 387 | -- 388 | 389 | ![bee42-logo.jpg](/images/bee42-logo.jpg) 390 | 391 | -- 392 | MIT License 393 | 394 | Copyright (c) 2017 Dieter Reuter 395 | -------------------------------------------------------------------------------- /part3-root-filesystem.md: -------------------------------------------------------------------------------- 1 | 2 | # Part 3: Root Filesystem 3 | 4 | The root filesystem of a Linux operating system contains all the files you need to run Linux. It is typically placed on an extra partition and should generally be pretty small to keep the system fast and secure. 5 | 6 | At the [Hypriot project](https://blog.hypriot.com) we based HypriotOS on the Linux distro Debian/Jessie and we already built a complete set of root filesystems for different CPU architectures. One of the basic goals of HypriotOS is to keep the Linux system itself as small as possible - so we just added the basic packages to the rootfs and did some basic customization. 7 | 8 | 9 | ## Building a Root filesystem 10 | 11 | Normally one would use the Debian tool "debootstrap" to create a new root filesystem for Debian/Jessie and there are some detailed documentation about [Debootstrap](https://wiki.debian.org/Debootstrap). It will take some time to get familiar with this tools and after some time you can create your own customized rootfs from scratch as well. 12 | 13 | At Hypriot we did this work already and there is a complete GitHub repo to build all these root filesystems at https://github.com/hypriot/os-rootfs. We also provide ready-to-download tarballs at the [GitHub releases](https://github.com/hypriot/os-rootfs/releases) of this project. 14 | 15 | And luckily we do have a ready tarball for ARMv8/ARM64/AARCH64 for Debian/Jessie, so it's just easy to take this one for our workshop to build a 64bit Docker-enabled Linux operating system for the Raspberry Pi 3. 16 | 17 | 18 | ## Contents of a Root Filesystem 19 | 20 | So lets download the latest version of this rootfs of HypriotOS and analyze it. 21 | ``` 22 | $ wget https://github.com/hypriot/os-rootfs/releases/download/v1.1.1/rootfs-arm64-debian-v1.1.1.tar.gz 23 | ``` 24 | 25 | The first thing we could see, it is really small in size with 116 MBytes only. 26 | ``` 27 | $ ls -alh rootfs-arm64-debian-v1.1.1.tar.gz 28 | -rw-r--r-- 1 dieter staff 116M Feb 27 17:05 rootfs-arm64-debian-v1.1.1.tar.gz 29 | ``` 30 | 31 | But yes, believe me, there are all necessary Debian packages included to boot into a full Linux system. 32 | ``` 33 | $ tar vtf rootfs-arm64-debian-v1.1.1.tar.gz | head -20 34 | drwxr-xr-x 0 root root 0 Feb 27 17:03 ./ 35 | drwxr-xr-x 0 root root 0 Feb 27 17:04 ./sbin/ 36 | lrwxrwxrwx 0 root root 0 Nov 8 2014 ./sbin/ip6tables -> xtables-multi 37 | -rwxr-xr-x 0 root root 14480 Nov 8 2014 ./sbin/ipmaddr 38 | lrwxrwxrwx 0 root root 0 Nov 8 2014 ./sbin/iptables-save -> xtables-multi 39 | -rwxr-xr-x 0 root root 74384 May 28 2016 ./sbin/dmsetup 40 | -rwxr-xr-x 0 root root 885 Feb 24 09:09 ./sbin/shadowconfig 41 | lrwxrwxrwx 0 root root 0 Sep 27 2014 ./sbin/modinfo -> /bin/kmod 42 | -rwxr-xr-x 0 root root 14504 Nov 13 16:15 ./sbin/pam_tally2 43 | -rwxr-xr-x 0 root root 10328 Mar 30 2015 ./sbin/fsfreeze 44 | -rwxr-xr-x 0 root root 102096 Dec 31 22:14 ./sbin/mke2fs 45 | -rwxr-xr-x 0 root root 6080 Apr 6 2015 ./sbin/fstab-decode 46 | lrwxrwxrwx 0 root root 0 Sep 27 2014 ./sbin/insmod -> /bin/kmod 47 | -rwxr-xr-x 0 root root 233968 Mar 30 2015 ./sbin/fdisk 48 | -rwxr-xr-x 0 root root 73088 Dec 31 22:14 ./sbin/tune2fs 49 | lrwxrwxrwx 0 root root 0 Jan 7 04:35 ./sbin/init -> /lib/systemd/systemd 50 | lrwxrwxrwx 0 root root 0 Sep 27 2014 ./sbin/rmmod -> /bin/kmod 51 | lrwxrwxrwx 0 root root 0 Dec 31 22:14 ./sbin/mkfs.ext2 -> mke2fs 52 | lrwxrwxrwx 0 root root 0 Sep 27 2014 ./sbin/depmod -> /bin/kmod 53 | -rwxr-xr-x 0 root root 27040 Mar 30 2015 ./sbin/blockdev 54 | ``` 55 | 56 | 57 | ## Recap 58 | 59 | This part of the workshop was really easy because we already have a ready-to-use tarball with the latest version of a pre-configured Debian/Jessie-based HypriotOS for our 64bit Raspberry Pi 3. 60 | 61 | Lets sum up what components we do have now: 62 | 63 | 1. Bootloader - specific for the Raspberry Pi 64 | 2. Kernel - a Linux kernel in 64bit with the current LTS version 4.9.13 compiled and configured for the Raspberry Pi 3 65 | 3. Root Filesystem - from HypriotOS based on Debian/Jessie for AARCH64 66 | 67 | So, these are finally all the components we need to build our complete operating system. The final construction will be covered in [Part 4 - SD Card Image](/part4-sd-card-image.md) where we'll create a bootable SD card and assemble all of the components we've built so far. 68 | 69 | -- 70 | 71 | ![bee42-logo.jpg](/images/bee42-logo.jpg) 72 | 73 | -- 74 | MIT License 75 | 76 | Copyright (c) 2017 Dieter Reuter 77 | -------------------------------------------------------------------------------- /part4-sd-card-image.md: -------------------------------------------------------------------------------- 1 | 2 | # Part 4: SD Card Image 3 | 4 | In the previous parts of our workshop to build a 64bit Docker OS for the Raspberry Pi 3 we're going through all the steps to create the basic building blocks and components we need: 5 | 6 | 1. [Bootloader](/part1-bootloader.md) - specific for the Raspberry Pi 7 | 2. [Kernel](/part2-kernel.md) - a Linux kernel in 64bit with the current LTS version 4.9.13 compiled and configured for the Raspberry Pi 3 8 | 3. [Root Filesystem](/part3-root-filesystem.md) - from HypriotOS based on Debian/Jessie for AARCH64 9 | 10 | 11 | ## TL;DR 12 | 13 | Here is the last repo to create the complete SD Card Image https://github.com/DieterReuter/image-builder-rpi64. 14 | 15 | You can download and flash the lastet of the SD Card Image from GitHub releases https://github.com/DieterReuter/image-builder-rpi64/releases/latest. 16 | 17 | * SD Image = hypriotos-rpi64-v20170303-185520.img.zip 18 | * Nodename = black-pearl 19 | * Username = pirate 20 | * Password = hypriot 21 | 22 | 23 | ## Final words...? 24 | 25 | I maybe will write some more details about the build process in a few days. But right now, feel free to use the final SD Card Image you can now download from the GitHub releases https://github.com/DieterReuter/image-builder-rpi64/releases/latest. 26 | 27 | -- 28 | 29 | ![bee42-logo.jpg](/images/bee42-logo.jpg) 30 | 31 | -- 32 | MIT License 33 | 34 | Copyright (c) 2017 Dieter Reuter 35 | --------------------------------------------------------------------------------