package main import ( "encoding/json" "fmt" "io" "log" "os" "os/exec" "path/filepath" "kisekinopureya.com.tr/updater/internal/archive" "kisekinopureya.com.tr/updater/internal/logger" mountfilesystem "kisekinopureya.com.tr/updater/internal/mountFilesystem" "kisekinopureya.com.tr/updater/internal/plymouth" ) type BlockDevice struct { Name string `json:"name"` Type string `json:"type"` PartType string `json:"parttype"` Children []BlockDevice `json:"children,omitempty"` } type LSBLK struct { BlockDevices []BlockDevice `json:"blockdevices"` } type partitionScheme struct { EfiDevice string RootfsDevice string DmVerityDevice string //VarDevice string } var efiUUID string = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" var rootfsUUID string = "4f68bce3-e8cd-4db1-96e7-fbcaf984b709" var dmverityUUID string = "2c7357ed-ebd2-46d9-aec1-23d437ec2bf5" //var varUUID string = "4d21b016-b534-45c2-a9fb-5c16e091fd2d" func findByPartType(devices []BlockDevice, target string) string { for _, dev := range devices { if dev.PartType != "" && dev.PartType == target { return dev.Name } if len(dev.Children) > 0 { if found := findByPartType(dev.Children, target); found != "" { return found } } } return "" } func populatePartitionScheme() partitionScheme { var generatedScheme partitionScheme = partitionScheme{} cmd := exec.Command("lsblk", "-J", "-o", "NAME,TYPE,PARTTYPE") blockDeviceTypes, err := cmd.Output() if err != nil { log.Panic(err) } var lsblk LSBLK if err := json.Unmarshal(blockDeviceTypes, &lsblk); err != nil { log.Panic(err) } generatedScheme.EfiDevice = findByPartType(lsblk.BlockDevices, efiUUID) generatedScheme.RootfsDevice = findByPartType(lsblk.BlockDevices, rootfsUUID) generatedScheme.DmVerityDevice = findByPartType(lsblk.BlockDevices, dmverityUUID) return generatedScheme } func patchImage(imageFile string, partition string, name string) { cmd := exec.Command("dd", "if="+imageFile, "of="+"/dev/"+partition, "bs=4M") plymouth.ShowPlymouthMessage("Patching " + name + " partition") if err := cmd.Run(); err != nil { log.Panic(err) } } func CopyFile(source, destPath string) error { in, err := os.Open(source) if err != nil { log.Panic(err) } defer in.Close() if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil { log.Panic(err) } out, err := os.Create(destPath) if err != nil { log.Panic(err) } defer out.Close() if _, err := io.Copy(out, in); err != nil { log.Panic(err) } if err := out.Sync(); err != nil { log.Panic(err) } return nil } func main() { logger.InitializeLogger("/mnt/var/log/patcher") if len(os.Args) != 2 { fmt.Printf("Usage: %s \n", os.Args[0]) os.Exit(1) } f, err := os.Open(os.Args[1]) if err != nil { panic(err) } defer f.Close() var meta archive.Output if err := json.NewDecoder(f).Decode(&meta); err != nil { panic(err) } currentPartitionScheme := populatePartitionScheme() fileCount := len(meta.Files) // before 20 and after 80 will be filled by initramfs leftProgress := 60/fileCount + 20 for _, f := range meta.Files { plymouth.ShowPlymouthProgress(leftProgress) leftProgress += leftProgress imageFile := f.Name imageType := f.Type switch imageType { case "rootfs": patchImage(imageFile, currentPartitionScheme.RootfsDevice, imageType) case "dm-verity": patchImage(imageFile, currentPartitionScheme.DmVerityDevice, imageType) case "kernel": mountPath := "/updates-tmp/efi" kernelDir := "/EFI/Linux" mountfilesystem.MountFileSystem("/dev/"+currentPartitionScheme.EfiDevice, mountPath, "vfat", 0, "") CopyFile(imageFile, mountPath+kernelDir+"/kernel.efi") mountfilesystem.UnmountFileSystem(mountPath) default: } } }