github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/multiboot/info.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 multiboot
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  
    11  	"github.com/mvdan/u-root-coreutils/pkg/ubinary"
    12  )
    13  
    14  var sizeofInfo = uint32(binary.Size(info{}))
    15  
    16  type flag uint32
    17  
    18  const (
    19  	flagInfoMemory flag = 1 << iota
    20  	flagInfoBootDev
    21  	flagInfoCmdline
    22  	flagInfoMods
    23  	flagInfoAoutSyms
    24  	flagInfoElfSHDR
    25  	flagInfoMemMap
    26  	flagInfoDriveInfo
    27  	flagInfoConfigTable
    28  	flagInfoBootLoaderName
    29  	flagInfoAPMTable
    30  	flagInfoVideoInfo
    31  	flagInfoFrameBuffer
    32  )
    33  
    34  // info represents the Multiboot v1 info passed to the loaded kernel.
    35  type info struct {
    36  	Flags    flag
    37  	MemLower uint32
    38  	MemUpper uint32
    39  
    40  	// BootDevice is not supported, always zero.
    41  	BootDevice uint32
    42  
    43  	Cmdline uint32
    44  
    45  	ModsCount uint32
    46  	ModsAddr  uint32
    47  
    48  	// Syms is not supported, always zero array.
    49  	Syms [4]uint32
    50  
    51  	MmapLength uint32
    52  	MmapAddr   uint32
    53  
    54  	// Following fields except BootLoaderName are not suppoted yet,
    55  	// the values are always set to zeros.
    56  
    57  	DriversLength uint32
    58  	DrivesrAddr   uint32
    59  
    60  	ConfigTable uint32
    61  
    62  	BootLoaderName uint32
    63  
    64  	APMTable uint32
    65  
    66  	VBEControlInfo  uint32
    67  	VBEModeInfo     uint32
    68  	VBEMode         uint16
    69  	VBEInterfaceSeg uint16
    70  	VBEInterfaceOff uint16
    71  	VBEInterfaceLen uint16
    72  
    73  	FramebufferAddr   uint16
    74  	FramebufferPitch  uint16
    75  	FramebufferWidth  uint32
    76  	FramebufferHeight uint32
    77  	FramebufferBPP    byte
    78  	FramebufferType   byte
    79  	ColorInfo         [6]byte
    80  }
    81  
    82  type infoWrapper struct {
    83  	info
    84  
    85  	Cmdline        string
    86  	BootLoaderName string
    87  }
    88  
    89  // marshal writes out the exact bytes of multiboot info
    90  // expected by the kernel being loaded.
    91  func (iw *infoWrapper) marshal(base uintptr) ([]byte, error) {
    92  	offset := sizeofInfo + uint32(base)
    93  	iw.info.Cmdline = offset
    94  	offset += uint32(len(iw.Cmdline)) + 1
    95  	iw.info.BootLoaderName = offset
    96  	iw.info.Flags |= flagInfoCmdline | flagInfoBootLoaderName
    97  
    98  	buf := bytes.Buffer{}
    99  	if err := binary.Write(&buf, ubinary.NativeEndian, iw.info); err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	for _, s := range []string{iw.Cmdline, iw.BootLoaderName} {
   104  		if _, err := buf.WriteString(s); err != nil {
   105  			return nil, err
   106  		}
   107  		if err := buf.WriteByte(0); err != nil {
   108  			return nil, err
   109  		}
   110  	}
   111  
   112  	size := (buf.Len() + 3) &^ 3
   113  	_, err := buf.Write(bytes.Repeat([]byte{0}, size-buf.Len()))
   114  	return buf.Bytes(), err
   115  }
   116  
   117  func (iw infoWrapper) size() (uint, error) {
   118  	b, err := iw.marshal(0)
   119  	return uint(len(b)), err
   120  }