mirror of
https://github.com/siderolabs/talos.git
synced 2025-12-15 14:31:18 +01:00
fix: generate images for SBCs using imager
See https://github.com/siderolabs/image-factory/issues/43 Two fixes: * pass path to the dtb, uboot and rpi-firmware explicitly * include dtb, uboot and rpi-firmware into arm64 installer image when generated via imager (regular arm64 installer was fine) (The generation of SBC images was not broken for Talos itself, but only when used via Image Factory). Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
parent
5dff164f1c
commit
cbe6e7622d
@ -285,7 +285,13 @@ func (i *Installer) Install(ctx context.Context, mode Mode) (err error) {
|
||||
|
||||
i.options.Printf("installing U-Boot for %q", b.Name())
|
||||
|
||||
if err = b.Install(i.options.Disk); err != nil {
|
||||
if err = b.Install(runtime.BoardInstallOptions{
|
||||
InstallDisk: i.options.Disk,
|
||||
UBootPath: i.options.BootAssets.UBootPath,
|
||||
DTBPath: i.options.BootAssets.DTBPath,
|
||||
RPiFirmwarePath: i.options.BootAssets.RPiFirmwarePath,
|
||||
Printf: i.options.Printf,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,10 +12,19 @@ type PartitionOptions struct {
|
||||
PartitionsOffset uint64
|
||||
}
|
||||
|
||||
// BoardInstallOptions are the board specific options for installation of various boot assets.
|
||||
type BoardInstallOptions struct {
|
||||
InstallDisk string
|
||||
DTBPath string
|
||||
UBootPath string
|
||||
RPiFirmwarePath string
|
||||
Printf func(string, ...any)
|
||||
}
|
||||
|
||||
// Board defines the requirements for a SBC.
|
||||
type Board interface {
|
||||
Name() string
|
||||
Install(string) error
|
||||
Install(options BoardInstallOptions) error
|
||||
KernelArgs() procfs.Parameters
|
||||
PartitionOptions() *PartitionOptions
|
||||
}
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package bananapim64
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,9 +18,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardBananaPiM64)
|
||||
bin = constants.BoardBananaPiM64 + "/u-boot-sunxi-with-spl.bin"
|
||||
off int64 = 1024 * 8
|
||||
dtb = "/dtb/allwinner/sun50i-a64-bananapi-m64.dtb"
|
||||
dtb = "allwinner/sun50i-a64-bananapi-m64.dtb"
|
||||
)
|
||||
|
||||
// BananaPiM64 represents the Banana Pi M64.
|
||||
@ -39,10 +37,10 @@ func (b *BananaPiM64) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (b *BananaPiM64) Install(disk string) (err error) {
|
||||
func (b *BananaPiM64) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
if f, err = os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
//nolint:errcheck
|
||||
@ -50,12 +48,12 @@ func (b *BananaPiM64) Install(disk string) (err error) {
|
||||
|
||||
var uboot []byte
|
||||
|
||||
uboot, err = os.ReadFile(bin)
|
||||
uboot, err = os.ReadFile(filepath.Join(options.UBootPath, bin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("writing %s at offset %d", bin, off)
|
||||
options.Printf("writing %s at offset %d", bin, off)
|
||||
|
||||
var n int
|
||||
|
||||
@ -64,7 +62,7 @@ func (b *BananaPiM64) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("wrote %d bytes", n)
|
||||
options.Printf("wrote %d bytes", n)
|
||||
|
||||
// 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
|
||||
@ -74,8 +72,8 @@ func (b *BananaPiM64) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dst), 0o600)
|
||||
if err != nil {
|
||||
|
||||
@ -21,7 +21,7 @@ import (
|
||||
// - https://github.com/u-boot/u-boot/blob/v2021.10/configs/p3450-0000_defconfig#L8
|
||||
// - https://github.com/u-boot/u-boot/blob/v2021.10/include/configs/tegra-common.h#L53
|
||||
// - https://github.com/u-boot/u-boot/blob/v2021.10/include/configs/tegra210-common.h#L49
|
||||
var dtb = "/dtb/nvidia/tegra210-p3450-0000.dtb"
|
||||
var dtb = "nvidia/tegra210-p3450-0000.dtb"
|
||||
|
||||
// JetsonNano represents the JetsonNano board
|
||||
//
|
||||
@ -35,10 +35,10 @@ func (b *JetsonNano) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (b JetsonNano) Install(disk string) (err error) {
|
||||
func (b JetsonNano) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
if f, err = os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
//nolint:errcheck
|
||||
@ -52,8 +52,8 @@ func (b JetsonNano) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dst), 0o600)
|
||||
if err != nil {
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package libretechallh3cch5
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,9 +18,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardLibretechAllH3CCH5)
|
||||
bin = constants.BoardLibretechAllH3CCH5 + "/u-boot-sunxi-with-spl.bin"
|
||||
off int64 = 1024 * 8
|
||||
dtb = "/dtb/allwinner/sun50i-h5-libretech-all-h3-cc.dtb"
|
||||
dtb = "allwinner/sun50i-h5-libretech-all-h3-cc.dtb"
|
||||
)
|
||||
|
||||
// LibretechAllH3CCH5 represents the Libre Computer ALL-H3-CC (Tritium).
|
||||
@ -36,10 +34,10 @@ func (l *LibretechAllH3CCH5) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (l *LibretechAllH3CCH5) Install(disk string) (err error) {
|
||||
func (l *LibretechAllH3CCH5) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
if f, err = os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
//nolint:errcheck
|
||||
@ -47,12 +45,12 @@ func (l *LibretechAllH3CCH5) Install(disk string) (err error) {
|
||||
|
||||
var uboot []byte
|
||||
|
||||
uboot, err = os.ReadFile(bin)
|
||||
uboot, err = os.ReadFile(filepath.Join(options.UBootPath, bin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("writing %s at offset %d", bin, off)
|
||||
options.Printf("writing %s at offset %d", bin, off)
|
||||
|
||||
var n int
|
||||
|
||||
@ -61,7 +59,7 @@ func (l *LibretechAllH3CCH5) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("wrote %d bytes", n)
|
||||
options.Printf("wrote %d bytes", n)
|
||||
|
||||
// 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
|
||||
@ -71,8 +69,8 @@ func (l *LibretechAllH3CCH5) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dst), 0o600)
|
||||
if err != nil {
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package nanopir4s
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,9 +18,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardNanoPiR4S)
|
||||
bin = constants.BoardNanoPiR4S + "u-boot-rockchip.bin"
|
||||
off int64 = 512 * 64
|
||||
dtb = "/dtb/rockchip/rk3399-nanopi-r4s.dtb"
|
||||
dtb = "rockchip/rk3399-nanopi-r4s.dtb"
|
||||
)
|
||||
|
||||
// NanoPiR4S represents the Friendlyelec Nano Pi R4S board.
|
||||
@ -36,27 +34,27 @@ func (n *NanoPiR4S) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (n *NanoPiR4S) Install(disk string) (err error) {
|
||||
file, err := os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666)
|
||||
func (n *NanoPiR4S) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
file, err := os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close() //nolint:errcheck
|
||||
|
||||
uboot, err := os.ReadFile(bin)
|
||||
uboot, err := os.ReadFile(filepath.Join(options.UBootPath, bin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("writing %s at offset %d", bin, off)
|
||||
options.Printf("writing %s at offset %d", bin, off)
|
||||
|
||||
amount, err := file.WriteAt(uboot, off)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("wrote %d bytes", amount)
|
||||
options.Printf("wrote %d bytes", amount)
|
||||
|
||||
// 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
|
||||
@ -65,8 +63,8 @@ func (n *NanoPiR4S) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(dst), 0o600); err != nil {
|
||||
return err
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package pine64
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,9 +18,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
bin = fmt.Sprintf("usr/install/arm64/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardPine64)
|
||||
bin = constants.BoardPine64 + "/u-boot-sunxi-with-spl.bin"
|
||||
off int64 = 1024 * 8
|
||||
dtb = "/dtb/allwinner/sun50i-a64-pine64-plus.dtb"
|
||||
dtb = "allwinner/sun50i-a64-pine64-plus.dtb"
|
||||
)
|
||||
|
||||
// Pine64 represents the Pine64 board
|
||||
@ -37,10 +35,10 @@ func (b *Pine64) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (b Pine64) Install(disk string) (err error) {
|
||||
func (b Pine64) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
if f, err = os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
//nolint:errcheck
|
||||
@ -48,12 +46,12 @@ func (b Pine64) Install(disk string) (err error) {
|
||||
|
||||
var uboot []byte
|
||||
|
||||
uboot, err = os.ReadFile(bin)
|
||||
uboot, err = os.ReadFile(filepath.Join(options.UBootPath, bin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("writing %s at offset %d", bin, off)
|
||||
options.Printf("writing %s at offset %d", bin, off)
|
||||
|
||||
var n int
|
||||
|
||||
@ -62,7 +60,7 @@ func (b Pine64) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("wrote %d bytes", n)
|
||||
options.Printf("wrote %d bytes", n)
|
||||
|
||||
// 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
|
||||
@ -72,8 +70,8 @@ func (b Pine64) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dst), 0o600)
|
||||
if err != nil {
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package rock64
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,9 +18,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardRock64)
|
||||
bin = constants.BoardRock64 + "/u-boot-rockchip.bin"
|
||||
off int64 = 512 * 64
|
||||
dtb = "/dtb/rockchip/rk3328-rock64.dtb"
|
||||
dtb = "rockchip/rk3328-rock64.dtb"
|
||||
)
|
||||
|
||||
// Rock64 represents the Pine64 Rock64 board.
|
||||
@ -36,10 +34,10 @@ func (r *Rock64) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (r *Rock64) Install(disk string) (err error) {
|
||||
func (r *Rock64) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
if f, err = os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
//nolint:errcheck
|
||||
@ -47,12 +45,12 @@ func (r *Rock64) Install(disk string) (err error) {
|
||||
|
||||
var uboot []byte
|
||||
|
||||
uboot, err = os.ReadFile(bin)
|
||||
uboot, err = os.ReadFile(filepath.Join(options.UBootPath, bin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("writing %s at offset %d", bin, off)
|
||||
options.Printf("writing %s at offset %d", bin, off)
|
||||
|
||||
var n int
|
||||
|
||||
@ -61,7 +59,7 @@ func (r *Rock64) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("wrote %d bytes", n)
|
||||
options.Printf("wrote %d bytes", n)
|
||||
|
||||
// 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
|
||||
@ -71,8 +69,8 @@ func (r *Rock64) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dst), 0o600)
|
||||
if err != nil {
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package rockpi4
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,11 +18,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardRockpi4)
|
||||
bin = constants.BoardRockpi4 + "/u-boot-rockchip.bin"
|
||||
off int64 = 512 * 64
|
||||
// https://github.com/u-boot/u-boot/blob/4de720e98d552dfda9278516bf788c4a73b3e56f/configs/rock-pi-4-rk3399_defconfig#L7=
|
||||
// 4a and 4b uses the same overlay.
|
||||
dtb = "/dtb/rockchip/rk3399-rock-pi-4b.dtb"
|
||||
dtb = "rockchip/rk3399-rock-pi-4b.dtb"
|
||||
)
|
||||
|
||||
// Rockpi4 represents the Radxa rock pi board.
|
||||
@ -38,21 +36,21 @@ func (r *Rockpi4) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (r *Rockpi4) Install(disk string) (err error) {
|
||||
func (r *Rockpi4) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
if f, err = os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
uboot, err := os.ReadFile(bin)
|
||||
uboot, err := os.ReadFile(filepath.Join(options.UBootPath, bin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("writing %s at offset %d", bin, off)
|
||||
options.Printf("writing %s at offset %d", bin, off)
|
||||
|
||||
var n int
|
||||
|
||||
@ -61,7 +59,7 @@ func (r *Rockpi4) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("wrote %d bytes", n)
|
||||
options.Printf("wrote %d bytes", n)
|
||||
|
||||
// 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
|
||||
@ -71,8 +69,8 @@ func (r *Rockpi4) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dst), 0o600)
|
||||
if err != nil {
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
package rockpi4c
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,10 +18,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardRockpi4)
|
||||
bin = constants.BoardRockpi4 + "/u-boot-rockchip.bin"
|
||||
off int64 = 512 * 64
|
||||
// https://github.com/u-boot/u-boot/blob/4de720e98d552dfda9278516bf788c4a73b3e56f/configs/rock-pi-4c-rk3399_defconfig#L7=
|
||||
dtb = "/dtb/rockchip/rk3399-rock-pi-4c.dtb"
|
||||
dtb = "rockchip/rk3399-rock-pi-4c.dtb"
|
||||
)
|
||||
|
||||
// Rockpi4c represents the Radxa rock pi board.
|
||||
@ -37,21 +35,21 @@ func (r *Rockpi4c) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (r *Rockpi4c) Install(disk string) (err error) {
|
||||
func (r *Rockpi4c) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(disk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
if f, err = os.OpenFile(options.InstallDisk, os.O_RDWR|unix.O_CLOEXEC, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
uboot, err := os.ReadFile(bin)
|
||||
uboot, err := os.ReadFile(filepath.Join(options.UBootPath, bin))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("writing %s at offset %d", bin, off)
|
||||
options.Printf("writing %s at offset %d", bin, off)
|
||||
|
||||
var n int
|
||||
|
||||
@ -60,7 +58,7 @@ func (r *Rockpi4c) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("wrote %d bytes", n)
|
||||
options.Printf("wrote %d bytes", n)
|
||||
|
||||
// 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
|
||||
@ -70,8 +68,8 @@ func (r *Rockpi4c) Install(disk string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
src := "/usr/install/arm64" + dtb
|
||||
dst := "/boot/EFI" + dtb
|
||||
src := filepath.Join(options.DTBPath, dtb)
|
||||
dst := filepath.Join("/boot/EFI/dtb", dtb)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(dst), 0o600)
|
||||
if err != nil {
|
||||
|
||||
@ -8,6 +8,7 @@ package rpigeneric
|
||||
import (
|
||||
_ "embed"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/siderolabs/go-procfs/procfs"
|
||||
|
||||
@ -30,13 +31,13 @@ func (r *RPiGeneric) Name() string {
|
||||
}
|
||||
|
||||
// Install implements the runtime.Board.
|
||||
func (r *RPiGeneric) Install(disk string) (err error) {
|
||||
err = copy.Dir("/usr/install/arm64/raspberrypi-firmware/boot", "/boot/EFI")
|
||||
func (r *RPiGeneric) Install(options runtime.BoardInstallOptions) (err error) {
|
||||
err = copy.Dir(filepath.Join(options.RPiFirmwarePath, "boot"), "/boot/EFI")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = copy.File("/usr/install/arm64/u-boot/rpi_generic/u-boot.bin", "/boot/EFI/u-boot.bin")
|
||||
err = copy.File(filepath.Join(options.UBootPath, "rpi_generic/u-boot.bin"), "/boot/EFI/u-boot.bin")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -35,13 +35,17 @@ type InstallOptions struct {
|
||||
Printf func(format string, v ...any)
|
||||
}
|
||||
|
||||
// BootAssets describes the assets to be installed by the booloader.
|
||||
// BootAssets describes the assets to be installed by the bootloader.
|
||||
type BootAssets struct {
|
||||
KernelPath string
|
||||
InitramfsPath string
|
||||
|
||||
UKIPath string
|
||||
SDBootPath string
|
||||
|
||||
DTBPath string
|
||||
UBootPath string
|
||||
RPiFirmwarePath string
|
||||
}
|
||||
|
||||
// FillDefaults fills in default paths to be used when in the context of the installer.
|
||||
@ -61,4 +65,18 @@ func (assets *BootAssets) FillDefaults(arch string) {
|
||||
if assets.SDBootPath == "" {
|
||||
assets.SDBootPath = fmt.Sprintf(constants.SDBootAssetPath, arch)
|
||||
}
|
||||
|
||||
if arch == "arm64" {
|
||||
if assets.DTBPath == "" {
|
||||
assets.DTBPath = fmt.Sprintf(constants.DTBAssetPath, arch)
|
||||
}
|
||||
|
||||
if assets.UBootPath == "" {
|
||||
assets.UBootPath = fmt.Sprintf(constants.UBootAssetPath, arch)
|
||||
}
|
||||
|
||||
if assets.RPiFirmwarePath == "" {
|
||||
assets.RPiFirmwarePath = fmt.Sprintf(constants.RPiFirmwareAssetPath, arch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
@ -22,6 +23,35 @@ type File struct {
|
||||
SourcePath string
|
||||
}
|
||||
|
||||
// Walk the filesystem generating a filemap.
|
||||
func Walk(sourceBasePath, imageBasePath string) ([]File, error) {
|
||||
var filemap []File
|
||||
|
||||
err := filepath.WalkDir(sourceBasePath, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
rel, err := filepath.Rel(sourceBasePath, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filemap = append(filemap, File{
|
||||
ImagePath: filepath.Join(imageBasePath, rel),
|
||||
SourcePath: path,
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return filemap, err
|
||||
}
|
||||
|
||||
// Layer creates a layer from a single file map.
|
||||
//
|
||||
// These layers are reproducible and consistent.
|
||||
|
||||
@ -188,10 +188,13 @@ func (i *Imager) buildImage(ctx context.Context, path string, printf func(string
|
||||
ImageSecureboot: i.prof.SecureBootEnabled(),
|
||||
Version: i.prof.Version,
|
||||
BootAssets: options.BootAssets{
|
||||
KernelPath: i.prof.Input.Kernel.Path,
|
||||
InitramfsPath: i.initramfsPath,
|
||||
UKIPath: i.ukiPath,
|
||||
SDBootPath: i.sdBootPath,
|
||||
KernelPath: i.prof.Input.Kernel.Path,
|
||||
InitramfsPath: i.initramfsPath,
|
||||
UKIPath: i.ukiPath,
|
||||
SDBootPath: i.sdBootPath,
|
||||
DTBPath: i.prof.Input.DTB.Path,
|
||||
UBootPath: i.prof.Input.UBoot.Path,
|
||||
RPiFirmwarePath: i.prof.Input.RPiFirmware.Path,
|
||||
},
|
||||
MountPrefix: scratchSpace,
|
||||
Printf: printf,
|
||||
@ -282,6 +285,37 @@ func (i *Imager) outInstaller(ctx context.Context, path string, report *reporter
|
||||
)
|
||||
}
|
||||
|
||||
for _, extraArtifact := range []struct {
|
||||
sourcePath string
|
||||
imagePath string
|
||||
}{
|
||||
{
|
||||
sourcePath: i.prof.Input.DTB.Path,
|
||||
imagePath: strings.TrimLeft(fmt.Sprintf(constants.DTBAssetPath, i.prof.Arch), "/"),
|
||||
},
|
||||
{
|
||||
sourcePath: i.prof.Input.UBoot.Path,
|
||||
imagePath: strings.TrimLeft(fmt.Sprintf(constants.UBootAssetPath, i.prof.Arch), "/"),
|
||||
},
|
||||
{
|
||||
sourcePath: i.prof.Input.RPiFirmware.Path,
|
||||
imagePath: strings.TrimLeft(fmt.Sprintf(constants.RPiFirmwareAssetPath, i.prof.Arch), "/"),
|
||||
},
|
||||
} {
|
||||
if extraArtifact.sourcePath == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
var extraFiles []filemap.File
|
||||
|
||||
extraFiles, err = filemap.Walk(extraArtifact.sourcePath, extraArtifact.imagePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to walk extra artifact %s: %w", extraArtifact.sourcePath, err)
|
||||
}
|
||||
|
||||
artifacts = append(artifacts, extraFiles...)
|
||||
}
|
||||
|
||||
artifactsLayer, err := filemap.Layer(artifacts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create artifacts layer: %w", err)
|
||||
|
||||
@ -21,6 +21,11 @@ import (
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
arm64 = "arm64"
|
||||
amd64 = "amd64"
|
||||
)
|
||||
|
||||
// Input describes inputs for image generation.
|
||||
type Input struct {
|
||||
// Kernel is a vmlinuz file.
|
||||
@ -31,6 +36,12 @@ type Input struct {
|
||||
SDStub FileAsset `yaml:"sdStub,omitempty"`
|
||||
// SDBoot is a sd-boot file (only for SecureBoot).
|
||||
SDBoot FileAsset `yaml:"sdBoot,omitempty"`
|
||||
// DTB is a path to the device tree blobs (arm64 only).
|
||||
DTB FileAsset `yaml:"dtb,omitempty"`
|
||||
// UBoot is a path to the u-boot binary (arm64 only).
|
||||
UBoot FileAsset `yaml:"uBoot,omitempty"`
|
||||
// RPiFirmware is a path to the Raspberry Pi firmware (arm64 only).
|
||||
RPiFirmware FileAsset `yaml:"rpiFirmware,omitempty"`
|
||||
// Base installer image to mutate.
|
||||
BaseInstaller ContainerAsset `yaml:"baseInstaller,omitempty"`
|
||||
// SecureBoot is a section with secureboot keys, only for SecureBoot enabled builds.
|
||||
@ -79,7 +90,7 @@ const defaultSecureBootPrefix = "/secureboot"
|
||||
|
||||
// FillDefaults fills default values for the input.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
//nolint:gocyclo,cyclop
|
||||
func (i *Input) FillDefaults(arch, version string, secureboot bool) {
|
||||
var (
|
||||
zeroFileAsset FileAsset
|
||||
@ -94,6 +105,20 @@ func (i *Input) FillDefaults(arch, version string, secureboot bool) {
|
||||
i.Initramfs.Path = fmt.Sprintf(constants.InitramfsAssetPath, arch)
|
||||
}
|
||||
|
||||
if arch == arm64 {
|
||||
if i.DTB == zeroFileAsset {
|
||||
i.DTB.Path = fmt.Sprintf(constants.DTBAssetPath, arch)
|
||||
}
|
||||
|
||||
if i.UBoot == zeroFileAsset {
|
||||
i.UBoot.Path = fmt.Sprintf(constants.UBootAssetPath, arch)
|
||||
}
|
||||
|
||||
if i.RPiFirmware == zeroFileAsset {
|
||||
i.RPiFirmware.Path = fmt.Sprintf(constants.RPiFirmwareAssetPath, arch)
|
||||
}
|
||||
}
|
||||
|
||||
if i.BaseInstaller == zeroContainerAsset {
|
||||
i.BaseInstaller.ImageRef = fmt.Sprintf("%s:%s", images.DefaultInstallerImageRepository, version)
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ func (p *Profile) SecureBootEnabled() bool {
|
||||
//
|
||||
//nolint:gocyclo,cyclop
|
||||
func (p *Profile) Validate() error {
|
||||
if p.Arch != "amd64" && p.Arch != "arm64" {
|
||||
if p.Arch != amd64 && p.Arch != arm64 {
|
||||
return fmt.Errorf("invalid arch %q", p.Arch)
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ func (p *Profile) Validate() error {
|
||||
}
|
||||
|
||||
if p.Board != "" {
|
||||
if !(p.Arch == "arm64" && p.Platform == "metal") {
|
||||
if !(p.Arch == arm64 && p.Platform == "metal") {
|
||||
return fmt.Errorf("board is only supported for metal arm64")
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,6 +529,15 @@ const (
|
||||
// SDBootAssetPath is the path to the SDBoot in the installer.
|
||||
SDBootAssetPath = "/usr/install/%s/" + SDBootAsset
|
||||
|
||||
// DTBAssetPath is the path to the device tree blobs in the installer.
|
||||
DTBAssetPath = "/usr/install/%s/dtb"
|
||||
|
||||
// UBootAssetPath is the path to the u-boot in the installer.
|
||||
UBootAssetPath = "/usr/install/%s/u-boot"
|
||||
|
||||
// RPiFirmwareAssetPath is the path to the raspberrypi firmware in the installer.
|
||||
RPiFirmwareAssetPath = "/usr/install/%s/raspberrypi-firmware"
|
||||
|
||||
// PlatformKeyAsset defines a well known name for the platform key filename used for auto-enrolling.
|
||||
PlatformKeyAsset = "PK.auth"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user