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