mirror of
https://github.com/siderolabs/talos.git
synced 2025-12-16 15:01:18 +01:00
Support generating multi profile UKIs. This PR adds the default wipe options. Fixes: #10190 Supporting extra profiles via imager would be another PR. Signed-off-by: Noel Georgi <git@frezbo.dev>
75 lines
2.3 KiB
Go
75 lines
2.3 KiB
Go
// 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 zboot provides a function to extract the kernel from a Zboot image.
|
|
package zboot
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
|
|
"github.com/klauspost/compress/zstd"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// Extract extracts the kernel from a Zboot image and returns a file descriptor of the extracted kernel.
|
|
func Extract(kernel *os.File) (int, io.Closer, error) {
|
|
// https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git/tree/include/kexec-pe-zboot.h
|
|
var peZbootheaderData [28]byte
|
|
|
|
if _, err := io.ReadFull(kernel, peZbootheaderData[:]); err != nil {
|
|
return 0, nil, err
|
|
}
|
|
|
|
// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/firmware/efi/libstub/zboot-header.S
|
|
// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/pe.h#n42
|
|
if !bytes.Equal(peZbootheaderData[:2], []byte("MZ")) {
|
|
return 0, nil, fmt.Errorf("invalid PE Zboot header")
|
|
}
|
|
|
|
// not a Zboot image, return
|
|
if !bytes.Equal(peZbootheaderData[4:8], []byte("zimg")) {
|
|
return int(kernel.Fd()), nil, nil
|
|
}
|
|
|
|
payloadOffset := binary.LittleEndian.Uint32(peZbootheaderData[8:12])
|
|
|
|
payloadSize := binary.LittleEndian.Uint32(peZbootheaderData[12:16])
|
|
|
|
if _, err := kernel.Seek(int64(payloadOffset), io.SeekStart); err != nil {
|
|
return 0, nil, fmt.Errorf("failed to seek to kernel zstd data from vmlinuz.efi: %w", err)
|
|
}
|
|
|
|
z, err := zstd.NewReader(io.LimitReader(kernel, int64(payloadSize)))
|
|
if err != nil {
|
|
return 0, nil, fmt.Errorf("failed to create zstd reader: %w", err)
|
|
}
|
|
|
|
defer z.Close()
|
|
|
|
fd, err := unix.MemfdCreate("vmlinux", 0)
|
|
if err != nil {
|
|
return 0, nil, fmt.Errorf("memfdCreate: %v", err)
|
|
}
|
|
|
|
kernelMemfd := os.NewFile(uintptr(fd), "vmlinux")
|
|
|
|
if _, err := io.Copy(kernelMemfd, z); err != nil {
|
|
kernelMemfd.Close() //nolint:errcheck
|
|
|
|
return 0, nil, fmt.Errorf("failed to copy zstd data to memfd: %w", err)
|
|
}
|
|
|
|
if _, err := kernelMemfd.Seek(0, io.SeekStart); err != nil {
|
|
kernelMemfd.Close() //nolint:errcheck
|
|
|
|
return 0, nil, fmt.Errorf("failed to seek to start of memfd: %w", err)
|
|
}
|
|
|
|
return fd, kernelMemfd, nil
|
|
}
|