github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/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  
    14  	"github.com/mvdan/u-root-coreutils/pkg/uio"
    15  )
    16  
    17  // DebugPrefix is a prefix that some messages are printed with for tests to parse.
    18  const DebugPrefix = "MULTIBOOT_DEBUG_INFO:"
    19  
    20  // Description stores representation of multiboot
    21  // information passed to a final kernel used for
    22  // for debugging and testing.
    23  type Description struct {
    24  	Status string `json:"status"`
    25  
    26  	Flags      uint32 `json:"flags"`
    27  	MemLower   uint32 `json:"mem_lower"`
    28  	MemUpper   uint32 `json:"mem_upper"`
    29  	MmapAddr   uint32 `json:"mmap_addr"`
    30  	MmapLength uint32 `json:"mmap_length"`
    31  
    32  	Cmdline    string `json:"cmdline"`
    33  	Bootloader string `json:"bootloader"`
    34  
    35  	Mmap    []MemoryMap  `json:"mmap"`
    36  	Modules []ModuleDesc `json:"modules"`
    37  }
    38  
    39  // Description returns string representation of
    40  // multiboot information.
    41  func (m multiboot) description() (string, error) {
    42  	var modules []ModuleDesc
    43  	for i, mod := range m.loadedModules {
    44  		b, err := uio.ReadAll(m.modules[i].Module)
    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].Cmdline,
    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  }