github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/pkg/multiboot/description.go (about)

     1  // Copyright 2019 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 multiboot
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/sha256"
    10  	"encoding/json"
    11  	"fmt"
    12  	"strconv"
    13  	"strings"
    14  )
    15  
    16  // DebugPrefix is a prefix that some messages are printed with for tests to parse.
    17  const DebugPrefix = "MULTIBOOT_DEBUG_INFO:"
    18  
    19  // Description stores representation of multiboot
    20  // information passed to a final kernel used for
    21  // for debugging and testing.
    22  type Description struct {
    23  	Status string `json:"status"`
    24  
    25  	Flags      uint32 `json:"flags"`
    26  	MemLower   uint32 `json:"mem_lower"`
    27  	MemUpper   uint32 `json:"mem_upper"`
    28  	MmapAddr   uint32 `json:"mmap_addr"`
    29  	MmapLength uint32 `json:"mmap_length"`
    30  
    31  	CmdLine    string `json:"cmdline"`
    32  	Bootloader string `json:"bootloader"`
    33  
    34  	Mmap    []MemoryMap  `json:"mmap"`
    35  	Modules []ModuleDesc `json:"modules"`
    36  }
    37  
    38  // Description returns string representation of
    39  // multiboot information.
    40  func (m multiboot) description() (string, error) {
    41  	var modules []ModuleDesc
    42  	for i, mod := range m.loadedModules {
    43  		name := strings.Fields(m.modules[i])[0]
    44  		b, err := readFile(name)
    45  		if err != nil {
    46  			return "", nil
    47  		}
    48  		hash := sha256.Sum256(b)
    49  		modules = append(modules, ModuleDesc{
    50  			Start:   mod.Start,
    51  			End:     mod.End,
    52  			CmdLine: m.modules[i],
    53  			SHA256:  fmt.Sprintf("%x", hash),
    54  		})
    55  
    56  	}
    57  
    58  	b, err := json.Marshal(Description{
    59  		Status:     "ok",
    60  		Flags:      uint32(m.info.Flags),
    61  		MemLower:   m.info.MemLower,
    62  		MemUpper:   m.info.MemUpper,
    63  		MmapAddr:   m.info.MmapAddr,
    64  		MmapLength: m.info.MmapLength,
    65  
    66  		CmdLine:    m.cmdLine,
    67  		Bootloader: m.bootloader,
    68  
    69  		Mmap:    m.memoryMap(),
    70  		Modules: modules,
    71  	})
    72  	if err != nil {
    73  		return "", err
    74  	}
    75  
    76  	b = bytes.Replace(b, []byte{'\n'}, []byte{' '}, -1)
    77  	return string(b), nil
    78  }
    79  
    80  // ModuleDesc is a debug representation of
    81  // loaded module.
    82  type ModuleDesc struct {
    83  	Start   uint32 `json:"start"`
    84  	End     uint32 `json:"end"`
    85  	CmdLine string `json:"cmdline"`
    86  	SHA256  string `json:"sha256"`
    87  }
    88  
    89  type mmap struct {
    90  	Size     uint32 `json:"size"`
    91  	BaseAddr string `json:"base_addr"`
    92  	Length   string `json:"length"`
    93  	Type     uint32 `json:"type"`
    94  }
    95  
    96  // MarshalJSON implements json.Marshaler
    97  func (m MemoryMap) MarshalJSON() ([]byte, error) {
    98  	return json.Marshal(mmap{
    99  		Size:     m.Size,
   100  		BaseAddr: fmt.Sprintf("%#x", m.BaseAddr),
   101  		Length:   fmt.Sprintf("%#x", m.Length),
   102  		Type:     m.Type,
   103  	})
   104  }
   105  
   106  // UnmarshalJSON implements json.Unmarshaler
   107  func (m *MemoryMap) UnmarshalJSON(b []byte) error {
   108  	var desc mmap
   109  	err := json.Unmarshal(b, &desc)
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	m.Size = desc.Size
   115  	m.Type = desc.Type
   116  	v, err := strconv.ParseUint(desc.BaseAddr, 0, 64)
   117  	if err != nil {
   118  		return err
   119  	}
   120  	m.BaseAddr = v
   121  
   122  	v, err = strconv.ParseUint(desc.Length, 0, 64)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	m.Length = v
   127  	return nil
   128  }