github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/bzimage/bzimage.go (about) 1 // Copyright 2012-2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // bzImage is used to modify bzImage files. 6 // It reads the image in, applies an operator, and writes a new one out. 7 // 8 // Synopsis: 9 // 10 // bzImage [copy <in> <out> ] | [diff <image> <image> ] | [dump <file>] | [initramfs input-bzimage initramfs output-bzimage] 11 // 12 // Description: 13 // 14 // Read a bzImage in, change it, write it out, or print info. 15 package main 16 17 import ( 18 "encoding/json" 19 "flag" 20 "fmt" 21 "io" 22 "log" 23 "os" 24 "strings" 25 26 "github.com/mvdan/u-root-coreutils/pkg/boot/bzimage" 27 "github.com/mvdan/u-root-coreutils/pkg/uroot/util" 28 ) 29 30 var argcounts = map[string]int{ 31 "copy": 3, 32 "diff": 3, 33 "dump": 2, 34 "initramfs": 4, 35 "extract": 3, 36 "ver": 2, 37 "cfg": 2, 38 } 39 40 const usage = `bzimage: 41 bzimage copy <in> <out> 42 Create a copy of <in> at <out>, parsing structures. 43 bzimage diff <image> <image> 44 Compare headers of two kernel images. 45 bzimage extract <file> <elf-file> 46 extract parts of the kernel into separate files with self- 47 explainatory extensions .boot, .head, .kern, .tail, .ramfs 48 bzimage dump <file> 49 Dumps header. 50 bzimage initramfs <input-bzimage> <new-initramfs> <output-bzimage> 51 Replaces initramfs in input-bzimage, creating output-bzimage. 52 bzimage ver <image> 53 Dump version info similar to 'file <image>'. 54 bzimage cfg <image> 55 Dump embedded config. 56 57 flags` 58 59 var ( 60 debug = flag.Bool("d", false, "enable debug printing") 61 jsonOut = flag.Bool("j", false, "json output ('ver' subcommand only)") 62 ) 63 64 func run(w io.Writer, args ...string) error { 65 if *debug { 66 bzimage.Debug = log.Printf 67 } 68 if len(args) < 2 { 69 flag.Usage() 70 return nil 71 } 72 n, ok := argcounts[args[0]] 73 if !ok || len(args) != n { 74 flag.Usage() 75 return nil 76 } 77 78 br := &bzimage.BzImage{} 79 var image []byte 80 switch args[0] { 81 case "diff", "dump", "ver": 82 br.NoDecompress = true 83 fallthrough 84 case "copy", "initramfs", "extract", "cfg": 85 var err error 86 image, err = os.ReadFile(args[1]) 87 if err != nil { 88 return err 89 } 90 if err = br.UnmarshalBinary(image); err != nil { 91 return err 92 } 93 } 94 95 switch args[0] { 96 case "copy": 97 o, err := br.MarshalBinary() 98 if err != nil { 99 return err 100 } 101 if len(image) != len(o) { 102 log.Printf("copy: input len is %d, output len is %d, they have to match", len(image), len(o)) 103 var br2 bzimage.BzImage 104 if err = br2.UnmarshalBinary(o); err != nil { 105 return err 106 } 107 fmt.Fprintf(w, "Input: %s\n", strings.Join(br.Header.Show(), "\n\t")) 108 fmt.Fprintf(w, "Output: %s\n", strings.Join(br2.Header.Show(), "\n\t")) 109 log.Printf("%s", br.Header.Diff(&br2.Header)) 110 return fmt.Errorf("there is no hope") 111 } 112 if err := os.WriteFile(args[2], o, 0o666); err != nil { 113 return fmt.Errorf("writing %v: %v", args[2], err) 114 } 115 case "diff": 116 b2, err := os.ReadFile(args[2]) 117 if err != nil { 118 return err 119 } 120 br2 := &bzimage.BzImage{} 121 if err = br2.UnmarshalBinary(b2); err != nil { 122 return err 123 } 124 fmt.Fprintf(w, "%s", br.Header.Diff(&br2.Header)) 125 case "dump": 126 fmt.Fprintf(w, "%s\n", strings.Join(br.Header.Show(), "\n")) 127 case "extract": 128 bzimage.Debug = log.Printf 129 var i []byte 130 s, e, err := br.InitRAMFS() 131 if err != nil { 132 fmt.Fprintf(w, "Warning: could not extract initramfs: %v", err) 133 } else { 134 i = br.KernelCode[s:e] 135 } 136 // Need to add a trailer record to i 137 fmt.Fprintf(w, "ramfs is %d bytes", len(i)) 138 139 for _, v := range []struct { 140 n string 141 b []byte 142 }{ 143 {args[2] + ".boot", br.BootCode}, 144 {args[2] + ".head", br.HeadCode}, 145 {args[2] + ".kern", br.KernelCode}, 146 {args[2] + ".tail", br.TailCode}, 147 {args[2] + ".ramfs", i}, 148 } { 149 if v.b == nil { 150 fmt.Fprintf(w, "Warning: %s is nil", v.n) 151 continue 152 } 153 if err := os.WriteFile(v.n, v.b, 0o666); err != nil { 154 return fmt.Errorf("writing %v: %v", v, err) 155 } 156 } 157 case "initramfs": 158 if err := br.AddInitRAMFS(args[2]); err != nil { 159 return err 160 } 161 162 b, err := br.MarshalBinary() 163 if err != nil { 164 return err 165 } 166 167 if err := os.WriteFile(args[3], b, 0o644); err != nil { 168 return err 169 } 170 case "ver": 171 v, err := br.KVer() 172 if err != nil { 173 return err 174 } 175 if *jsonOut { 176 info, err := bzimage.ParseDesc(v) 177 if err != nil { 178 return err 179 } 180 j, err := json.MarshalIndent(info, "", " ") 181 if err != nil { 182 return err 183 } 184 fmt.Fprintln(w, string(j)) 185 } else { 186 fmt.Fprintln(w, v) 187 } 188 case "cfg": 189 cfg, err := br.ReadConfig() 190 if err != nil { 191 return err 192 } 193 fmt.Fprintf(w, "%s\n", cfg) 194 } 195 return nil 196 } 197 198 func main() { 199 flag.Usage = util.Usage(flag.Usage, usage) 200 flag.Parse() 201 if err := run(os.Stdout, flag.Args()...); err != nil { 202 log.Fatal(err) 203 } 204 }