gokrazy-cm3588-kernel/cmd/gokr-rebuild-kernel/kernel.go
Anup Chenthamarakshan fae11c0881 rock64 kernel and u-boot
- Based on https://github.com/anupcshan/gokrazy-odroidxu4-kernel/
- Build functioning u-boot-rockchip.bin
- Generate basic kernel and clean up XU4 files
- Rename vmlinux -> vmlinuz to make Gokrazy plumbing easier
- Enable squashfs root config
- Enable STMMAC - network works, but eth has the same MAC address for all devices :\
- Enable other Rockchip config entities
- Fix setexpr string termination
2024-01-11 21:54:02 -08:00

246 lines
5.6 KiB
Go

package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
"text/template"
)
const dockerFileContents = `
FROM debian:bullseye
RUN apt-get update && apt-get install -y crossbuild-essential-arm64 bc libssl-dev bison flex
COPY gokr-build-kernel /usr/bin/gokr-build-kernel
{{- range $idx, $path := .Patches }}
COPY {{ $path }} /usr/src/{{ $path }}
{{- end }}
RUN echo 'builduser:x:{{ .Uid }}:{{ .Gid }}:nobody:/:/bin/sh' >> /etc/passwd && \
chown -R {{ .Uid }}:{{ .Gid }} /usr/src
USER builduser
WORKDIR /usr/src
ENTRYPOINT /usr/bin/gokr-build-kernel
`
var dockerFileTmpl = template.Must(template.New("dockerfile").
Funcs(map[string]interface{}{
"basename": func(path string) string {
return filepath.Base(path)
},
}).
Parse(dockerFileContents))
var patchFiles = []string{
// "0001-ODROID-XU4-regulator-s2mps11-call-shutdown-function-.patch",
// "0002-ODROID-XU4-regulator-s2mps11-add-ethernet-power-rese.patch",
}
func copyFile(dest, src string) error {
out, err := os.Create(dest)
if err != nil {
return err
}
defer out.Close()
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
if _, err := io.Copy(out, in); err != nil {
return err
}
st, err := in.Stat()
if err != nil {
return err
}
if err := out.Chmod(st.Mode()); err != nil {
return err
}
return out.Close()
}
var gopath = mustGetGopath()
func mustGetGopath() string {
gopathb, err := exec.Command("go", "env", "GOPATH").Output()
if err != nil {
log.Panic(err)
}
return strings.TrimSpace(string(gopathb))
}
func find(filename string) (string, error) {
if _, err := os.Stat(filename); err == nil {
return filename, nil
}
path := filepath.Join(gopath, "src", "github.com", "anupcshan", "gokrazy-rock64-kernel", filename)
if _, err := os.Stat(path); err == nil {
return path, nil
}
return "", fmt.Errorf("could not find file %q (looked in . and %s)", filename, path)
}
func getContainerExecutable() (string, error) {
// Probe podman first, because the docker binary might actually
// be a thin podman wrapper with podman behavior.
choices := []string{"podman", "docker"}
for _, exe := range choices {
p, err := exec.LookPath(exe)
if err != nil {
continue
}
resolved, err := filepath.EvalSymlinks(p)
if err != nil {
return "", err
}
return resolved, nil
}
return "", fmt.Errorf("none of %v found in $PATH", choices)
}
func main() {
var overwriteContainerExecutable = flag.String("overwrite_container_executable",
"",
"E.g. docker or podman to overwrite the automatically detected container executable")
flag.Parse()
executable, err := getContainerExecutable()
if err != nil {
log.Fatal(err)
}
if *overwriteContainerExecutable != "" {
executable = *overwriteContainerExecutable
}
execName := filepath.Base(executable)
// We explicitly use /tmp, because Docker only allows volume mounts under
// certain paths on certain platforms, see
// e.g. https://docs.docker.com/docker-for-mac/osxfs/#namespaces for macOS.
tmp, err := ioutil.TempDir("/tmp", "gokr-rebuild-kernel")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(tmp)
cmd := exec.Command("go", "install", "github.com/anupcshan/gokrazy-rock64-kernel/cmd/gokr-build-kernel")
cmd.Env = append(os.Environ(), "GOOS=linux", "CGO_ENABLED=0", "GOBIN="+tmp)
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalf("%v: %v", cmd.Args, err)
}
buildPath := filepath.Join(tmp, "gokr-build-kernel")
var patchPaths []string
for _, filename := range patchFiles {
path, err := find(filename)
if err != nil {
log.Fatal(err)
}
patchPaths = append(patchPaths, path)
}
kernelPath, err := find("vmlinuz")
if err != nil {
log.Fatal(err)
}
dtbPath, err := find("rk3328-rock64.dtb")
if err != nil {
log.Fatal(err)
}
// Copy all files into the temporary directory so that docker
// includes them in the build context.
for _, path := range patchPaths {
if err := copyFile(filepath.Join(tmp, filepath.Base(path)), path); err != nil {
log.Fatal(err)
}
}
u, err := user.Current()
if err != nil {
log.Fatal(err)
}
dockerFile, err := os.Create(filepath.Join(tmp, "Dockerfile"))
if err != nil {
log.Fatal(err)
}
if err := dockerFileTmpl.Execute(dockerFile, struct {
Uid string
Gid string
BuildPath string
Patches []string
}{
Uid: u.Uid,
Gid: u.Gid,
BuildPath: buildPath,
Patches: patchFiles,
}); err != nil {
log.Fatal(err)
}
if err := dockerFile.Close(); err != nil {
log.Fatal(err)
}
log.Printf("building %s container for kernel compilation", execName)
dockerBuild := exec.Command(execName,
"build",
"--rm=true",
"--tag=gokr-rebuild-kernel",
".")
dockerBuild.Dir = tmp
dockerBuild.Stdout = os.Stdout
dockerBuild.Stderr = os.Stderr
if err := dockerBuild.Run(); err != nil {
log.Fatalf("%s build: %v (cmd: %v)", execName, err, dockerBuild.Args)
}
log.Printf("compiling kernel")
var dockerRun *exec.Cmd
if execName == "podman" {
dockerRun = exec.Command(executable,
"run",
"--userns=keep-id",
"--rm",
"--volume", tmp+":/tmp/buildresult:Z",
"gokr-rebuild-kernel")
} else {
dockerRun = exec.Command(executable,
"run",
"--rm",
"--volume", tmp+":/tmp/buildresult:Z",
"gokr-rebuild-kernel")
}
dockerRun.Dir = tmp
dockerRun.Stdout = os.Stdout
dockerRun.Stderr = os.Stderr
if err := dockerRun.Run(); err != nil {
log.Fatalf("%s run: %v (cmd: %v)", execName, err, dockerRun.Args)
}
if err := copyFile(kernelPath, filepath.Join(tmp, "vmlinuz")); err != nil {
log.Fatal(err)
}
if err := copyFile(dtbPath, filepath.Join(tmp, "rk3328-rock64.dtb")); err != nil {
log.Fatal(err)
}
}