Skip to content

Commit

Permalink
feat: add ODroid HC4 support
Browse files Browse the repository at this point in the history
Adds support for the ODroid HC4 SBC.

Signed-off-by: Brandon McNama <[email protected]>
  • Loading branch information
DWSR committed Sep 22, 2023
1 parent a52d3cd commit c403f03
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 0 deletions.
3 changes: 3 additions & 0 deletions internal/app/machined/pkg/runtime/v1alpha1/board/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
jetsonnano "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board/jetson_nano"
libretechallh3cch5 "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board/libretech_all_h3_cc_h5"
nanopir4s "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board/nanopi_r4s"
odroidhc4 "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board/odroid_hc4"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board/pine64"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board/rock64"
rockpi4 "github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/board/rockpi4"
Expand Down Expand Up @@ -70,6 +71,8 @@ func newBoard(board string) (b runtime.Board, err error) {
b = &jetsonnano.JetsonNano{}
case constants.BoardNanoPiR4S:
b = &nanopir4s.NanoPiR4S{}
case constants.BoardODroidHC4:
b = &odroidhc4.ODroidHC4{}
default:
return nil, fmt.Errorf("unsupported board: %q", board)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package odroidhc4 provides the ODroid HC4 board implementation.
package odroidhc4

import (
"log"
"os"
"path/filepath"

"github.com/siderolabs/go-procfs/procfs"
"golang.org/x/sys/unix"

"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
"github.com/siderolabs/talos/pkg/copy"
"github.com/siderolabs/talos/pkg/machinery/constants"
)

var dtb = "/amlogic/meson-sm1-odroid-hc4.dtb"

// ODroidHC4 represents the ODroid HC4.
//
// References:
// - https://wiki.odroid.com/odroid-hc4/odroid-hc4
// - https://wiki.odroid.com/odroid-hc4/software/partition_table
// - https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/odroid-c4.rst
type ODroidHC4 struct{}

// Name implements the runtime.Board.
func (b *ODroidHC4) Name() string {
return constants.BoardODroidHC4
}

// Install implements the runtime.Board.
func (b *ODroidHC4) Install(disk string) (err error) {
var f *os.File

if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
return err
}
//nolint:errcheck
defer f.Close()

// NB: In the case that the block device is a loopback device, we sync here
// to esure that the file is written before the loopback device is
// unmounted.
err = f.Sync()
if err != nil {
return err
}

src := "/usr/install/arm64/dtb" + dtb
dst := "/boot/EFI" + dtb

log.Printf("write %s to %s", src, dst)

err = os.MkdirAll(filepath.Dir(dst), 0o600)
if err != nil {
return err
}

err = copy.File(src, dst)
if err != nil {
return err
}

log.Printf("wrote %s to %s", src, dst)

return nil
}

// KernelArgs implements the runtime.Board.
func (b *ODroidHC4) KernelArgs() procfs.Parameters {
return []*procfs.Parameter{
// https://wiki.odroid.com/odroid-hc4/application_note/misc/dmesg_on_display
procfs.NewParameter("console").Append("tty1").Append("ttyAML0,115200n8"),
}
}

// PartitionOptions implements the runtime.Board.
func (b *ODroidHC4) PartitionOptions() *runtime.PartitionOptions {
return &runtime.PartitionOptions{PartitionsOffset: 2048}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

//go:build !amd64

// Package vmware provides the VMware platform implementation.
package vmware

import (
Expand Down
3 changes: 3 additions & 0 deletions pkg/machinery/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ const (
// BoardNanoPiR4S is the name of the Friendlyelec Nano Pi R4S.
BoardNanoPiR4S = "nanopi_r4s"

// BoardODroidHC4 is the name of the HardKernel ODroid HC4.
BoardODroidHC4 = "odroid_hc4"

// KernelParamHostname is the kernel parameter name for specifying the
// hostname.
KernelParamHostname = "talos.hostname"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: "ODroid HC4"
description: "Installing Talos on an ODroid HC4 SBC using raw disk image."
aliases:
- ../../../single-board-computers/odroid_hc4
---
## Prerequisites

You will need:

- `talosctl`
- A microSD card to prepare the unit with
- An additional microSD card, USB stick, or SATA drive to boot Talos from

Download the latest `talosctl`:

```shell
curl -Lo /usr/local/bin/talosctl https://github.com/siderolabs/talos/releases/download/v1.4.0/talosctl-$(uname -s | tr "[:upper:]" "[:lower:]")-amd64

chmod +x /usr/local/bin/talosctl
```

## Download and Write the Image

Download the image and decompress it:

```shell
curl -LO https://github.com/siderolabs/talos/releases/download/v1.4.0/metal-odroid_hc4-arm64.img.xz | xz -d -

xz -d metal-odroid_hc4-arm64.img.xz
```

Write the image to the chosen boot media via [BalenaEtcher](https://www.balena.io/etcher) or `dd`.

## Prepare the Unit

### Erase factory bootloader

- Boot device to petitboot (no USB, SDCard, etc.), the default bootloader
- In petitboot menu, select `Exit to shell`
- Run the following:

```shell
flash_eraseall /dev/mtd0
flash_eraseall /dev/mtd1
flash_eraseall /dev/mtd2
flash_eraseall /dev/mtd3
```

- Power cycle the device

### Install u-boot to SPI

- Flash [Armbian](https://www.armbian.com/odroid-hc4/) to a micro SD card with `dd` or [BalenaEtcher](https://www.balena.io/etcher).
**A bootable USB stick or SATA drive will not work for this step**
- Insert the Armbian micro SD card into the unit and power it on.
- Once Armbian is booted, install `crane` via the following commands.
Make sure the unit is connected to the Internet:

```shell
curl -L https://api.github.com/repos/google/go-containerregistry/releases/latest |
jq -r '.assets[] | select(.name | contains("Linux_arm64")) | .browser_download_url' |
xargs curl -sL |
tar zxvf - && \
install crane /usr/bin
```

- Extract the `u-boot` image from the Talos installer:

```shell
mkdir _out
crane --platform=linux/arm64 export ghcr.io/siderolabs/u-boot:v1.4.0 - | tar xf - --strip-components=1 -C _out odroid_hc4/u-boot.bin
```

- Write `u-boot.bin` to the HC4's SPI/bootloader:

```shell
dd if=_out/u-boot.bin of=/dev/mtdblock0 conv=fsync status=progress
```

- Power off the unit

## Recover Factory Bootloader

**Note:** Only perform these steps if you want to use Hardkernel-published distributions.
Performing these actions will render the unit unable to boot Talos unless the steps in this guide are repeated.

Taken from [the ODroid forums](https://forum.odroid.com/viewtopic.php?t=40906):

- Download the latest `spiupdate` and `spiboot` archives from [here](http://ppa.linuxfactory.or.kr/images/petitboot/odroidhc4/).
- Flash the `spiupdate` image to a microSD card via `dd` or `dd` or [BalenaEtcher](https://www.balena.io/etcher).
- Decompress the `spiboot` archive and copy the file it contains to the flashed SD card.
Ensure the file is named `spiboot.img`.
- Insert the microSD card into the unit and power it on

0 comments on commit c403f03

Please sign in to comment.