github.com/shaardie/u-root@v4.0.1-0.20190127173353-f24a1c26aa2e+incompatible/pkg/multiboot/header.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 // Multiboot header as defined in 6 // https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Header-layout 7 package multiboot 8 9 import ( 10 "bytes" 11 "encoding/binary" 12 "errors" 13 "io" 14 "log" 15 16 "github.com/u-root/u-root/pkg/ubinary" 17 ) 18 19 var ErrHeaderNotFound = errors.New("multiboot header not found") 20 var ErrFlagsNotSupported = errors.New("multiboot header flags not supported yet") 21 22 const headerMagic = 0x1BADB002 23 24 const ( 25 flagHeaderPageAlign Flag = 0x00000001 26 flagHeaderMemoryInfo = 0x00000002 27 28 // ignore this flag for now 29 flagHeaderMultibootVideoMode = 0x00000004 30 31 flagHeaderUnsupported = 0x0000FFF8 32 ) 33 34 // mandatory is a mandatory part of Multiboot v1 header. 35 type mandatory struct { 36 Magic uint32 37 Flags Flag 38 Checksum uint32 39 } 40 41 // optional is an optional part of Multiboot v1 header. 42 type optional struct { 43 HeaderAddr uint32 44 LoadAddr uint32 45 LoadEndAddr uint32 46 BSSEndAddr uint32 47 EntryAddr uint32 48 49 ModeType uint32 50 Width uint32 51 Height uint32 52 Depth uint32 53 } 54 55 // Header represents a Multiboot v1 header loaded from the file. 56 type Header struct { 57 mandatory 58 optional 59 } 60 61 // parseHeader parses multiboot header as defined in 62 // https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#OS-image-format 63 func parseHeader(r io.Reader) (Header, error) { 64 mandatorySize := binary.Size(mandatory{}) 65 optionalSize := binary.Size(optional{}) 66 sizeofHeader := mandatorySize + optionalSize 67 var hdr Header 68 // The multiboot header must be contained completely within the 69 // first 8192 bytes of the OS image. 70 buf := make([]byte, 8192) 71 n, err := io.ReadAtLeast(r, buf, mandatorySize) 72 if err != nil { 73 return hdr, err 74 } 75 buf = buf[:n] 76 77 // Append zero bytes to the end of buffer to be able to read hdr 78 // in a single binary.Read() when the mandatory 79 // part of the header starts near the 8192 boundary. 80 buf = append(buf, make([]byte, optionalSize)...) 81 br := new(bytes.Reader) 82 for len(buf) >= sizeofHeader { 83 br.Reset(buf) 84 if err := binary.Read(br, ubinary.NativeEndian, &hdr); err != nil { 85 return hdr, err 86 } 87 if hdr.Magic == headerMagic && (hdr.Magic+uint32(hdr.Flags)+hdr.Checksum) == 0 { 88 if hdr.Flags&flagHeaderUnsupported != 0 { 89 return hdr, ErrFlagsNotSupported 90 } 91 if hdr.Flags&flagHeaderMultibootVideoMode != 0 { 92 log.Print("VideoMode flag is not supproted yet, trying to load anyway") 93 } 94 return hdr, nil 95 } 96 // The Multiboot header must be 32-bit aligned. 97 buf = buf[4:] 98 } 99 return hdr, ErrHeaderNotFound 100 }