github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/pkg/boot/linux.go (about) 1 // Copyright 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 package boot 6 7 import ( 8 "errors" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "log" 13 "os" 14 15 "github.com/u-root/u-root/pkg/kexec" 16 "github.com/u-root/u-root/pkg/uio" 17 ) 18 19 // LinuxImage implements OSImage for a Linux kernel + initramfs. 20 type LinuxImage struct { 21 Kernel io.ReaderAt 22 Initrd io.ReaderAt 23 Cmdline string 24 } 25 26 var _ OSImage = &LinuxImage{} 27 28 // String prints a human-readable version of this linux image. 29 func (li *LinuxImage) String() string { 30 return fmt.Sprintf("LinuxImage(\n Kernel: %s\n Initrd: %s\n Cmdline: %s\n)\n", li.Kernel, li.Initrd, li.Cmdline) 31 } 32 33 func copyToFile(r io.Reader) (*os.File, error) { 34 f, err := ioutil.TempFile("", "nerf-netboot") 35 if err != nil { 36 return nil, err 37 } 38 defer f.Close() 39 if _, err := io.Copy(f, r); err != nil { 40 return nil, err 41 } 42 if err := f.Sync(); err != nil { 43 return nil, err 44 } 45 46 readOnlyF, err := os.Open(f.Name()) 47 if err != nil { 48 return nil, err 49 } 50 return readOnlyF, nil 51 } 52 53 // Load implements OSImage.Load and kexec_load's the kernel with its initramfs. 54 func (li *LinuxImage) Load(verbose bool) error { 55 if li.Kernel == nil { 56 return errors.New("LinuxImage.Kernel must be non-nil") 57 } 58 59 kernel, initrd := uio.Reader(li.Kernel), uio.Reader(li.Initrd) 60 if verbose { 61 // In verbose mode, print a dot every 5MiB. It is not pretty, 62 // but it at least proves the files are still downloading. 63 progress := func(r io.Reader) io.Reader { 64 return &uio.ProgressReader{ 65 R: r, 66 Symbol: ".", 67 Interval: 5 * 1024 * 1024, 68 W: os.Stdout, 69 } 70 } 71 kernel = progress(kernel) 72 initrd = progress(initrd) 73 } 74 75 k, err := copyToFile(kernel) 76 if err != nil { 77 return err 78 } 79 defer k.Close() 80 81 var i *os.File 82 if li.Initrd != nil { 83 i, err = copyToFile(initrd) 84 if err != nil { 85 return err 86 } 87 defer i.Close() 88 } 89 90 log.Printf("Kernel: %s", k.Name()) 91 if i != nil { 92 log.Printf("Initrd: %s", i.Name()) 93 } 94 log.Printf("Command line: %s", li.Cmdline) 95 return kexec.FileLoad(k, i, li.Cmdline) 96 }