func mountOverlay() {
	tmpdirs := []string{"/tmp/upper", "/tmp/work"}
	for _, dir := range tmpdirs {
		err := os.MkdirAll(dir, 0755)
		if err != nil {
			log.Fatalf("Mkdir(%s): %v", dir, err)
		}
	}
	mount("overlayfs")
}
mountOverlay mounts the overlayfs on top of the ro root
package main
import (
	"bytes"
	"context"
	"crypto"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"time"
	"github.com/machinebox/progress"
	"github.com/u-root/u-root/pkg/boot"
	"github.com/u-root/u-root/pkg/boot/kexec"
	"github.com/u-root/u-root/pkg/kmodule"
	uroot "github.com/u-root/u-root/pkg/mount"
	"github.com/u-root/u-root/pkg/uio"
	"golang.org/x/crypto/openpgp/errors"
	"golang.org/x/crypto/openpgp/packet"
	"golang.org/x/sys/unix"
)
const (
	pubKeyPath = "/u-bmc.pub"
	kernelPath = "/ro/boot/zImage"
	dtbPath    = "/ro/boot/platform.dtb"
	initPath   = "/ro/bin/init"
)
var (
	kload  = flag.Bool("kexec", false, "Mount rootfs and call kexec")
	swroot = flag.Bool("switch", false, "Mount rootfs and call switch_root")
	mtd    = flag.Bool("mtd", false, "Mount and load u-bmc from MTD flash")
	blk    = flag.Bool("blk", false, "Mount and load u-bmc from block device")
	ast    = flag.Bool("ast", false, "ASPEED ast specific option")
	verify = []string{initPath, kernelPath, dtbPath}
)
func main() {
	flag.Parse()
	if *mtd && *blk {
		log.Fatal("mtd and blk are mutually exclusive!")
	}
	if !*mtd && !*blk {
		log.Fatal("please choose either mtd or blk!")
	}
	if *kload && *swroot {
		log.Fatal("kexec and switch are mutually exclusive!")
	}
	if !*kload && !*swroot {
		log.Fatal("please choose either kexec or switch!")
	}
	if *ast {
		err := loadModule("/bootlock.ko")
		if err != nil {
			log.Fatalf("loadModule(/bootlock.ko): %v", err)
		}
	}
	if *kload {
		loadAndExec()
	}
	if *swroot {
		mountAndSwitchRoot()
	}
}
func mountAndSwitchRoot() {
	createBasicHirarchy()
	if *mtd {
		mountMtd()
	}
	if *blk {
		mountBlk()
	}
	mountOverlay()
	err := uroot.SwitchRoot("/mnt", "/bin/init")
	if err != nil {
		log.Fatalf("SwitchRoot: %v", err)
	}
}
func loadAndExec() {
	keyf, err := os.Open(pubKeyPath)
	if err != nil {
		log.Fatalf("Open(%s): %v", pubKeyPath, err)
	}
	key, err := readPublicSigningKey(keyf)
	if err != nil {
		log.Fatalf("readPublicSigningKey(%s): %v", pubKeyPath, err)
	}
	createBasicHirarchy()
	if *mtd {
		mountMtd()
	}
	if *blk {
		mountBlk()
	}
	for _, path := range verify {
		f, err := openAndVerify(path, key)
		if err != nil {
			log.Fatalf("openAndVerify(%s): %v", path, err)
		}
		f.Close()
	}
	log.Printf("Integrity check OK")
	kernel, err := os.Open(kernelPath)
	if err != nil {
		log.Fatalf("Open(%s): %v", kernelPath, err)
	}
	err = kexec.FileLoad(kernel, nil, "")
	if err != nil {
		log.Fatalf("KexecFileLoad: %v", err)
	}
	kernel.Close()
	log.Print("Looks like kexec_file_load didn't work, let's try kexec_load")
	image := &boot.LinuxImage{
		Kernel: uio.NewLazyFile(kernelPath),
	}
	err = image.Load(true)
	if err != nil {
		log.Fatalf("Load(%s): %v", kernelPath, err)
	}
	err = kexec.Reboot()
	if err != nil {
		log.Fatalf("Reboot: %v", err)
	}
}
func createBasicHirarchy() {
	dirs := []string{"/mnt", "/ro", "/tmp", "/proc", "/sys", "/dev"}
	for _, dir := range dirs {
		err := os.MkdirAll(dir, 0755)
		if err != nil {
			log.Fatalf("Mkdir(%s): %v", dir, err)
		}
	}
	mnts := []string{"sysfs", "proc", "devtmpfs", "tmpfs"}
	for _, mnt := range mnts {
		mount(mnt)
	}
	err := os.MkdirAll("/dev/pts", 0755)
	if err != nil {
		log.Fatalf("Mkdir(/dev/pts): %v", err)
	}
	mount("devpts")
}
func mountMtd() {
	err := unix.Mount("ubi0:root", "/ro", "ubifs", unix.MS_RDONLY, "")
	if err != nil {
		log.Fatalf("Mount(ubi0:root): %v", err)
	}
}
func mountBlk() {
	var offset int64 = 1072  
	var data = make([]byte, 16)
	var uuid = []byte{0x26, 0xab, 0x04, 0x01, 0x3f, 0x49, 0x4f, 0xc2, 0xa1, 0x72, 0xc8, 0xaa, 0x02, 0xac, 0xea, 0xf3}
	devs, _ := filepath.Glob("/sys/class/block/*")
	for _, dev := range devs {
		dev = "/dev/" + filepath.Base(dev)
		bd, err := os.Open(dev)
		if err != nil {
			log.Fatalf("Open(%s): %v", dev, err)
		}
		_, err = bd.ReadAt(data, offset)
		bd.Close()
		if err == nil && bytes.Equal(data, uuid) {
			err = unix.Mount(dev, "/ro", "erofs", unix.MS_RDONLY, "")
			if err != nil {
				log.Fatalf("Mount(%s): %v", dev, err)
			}
		}
	}
}