Bitmap font format for the GRUB 2 bootloader.
This page hosts a formal specification of GRUB 2 font using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"bytes"
"io"
)
/**
* Bitmap font format for the GRUB 2 bootloader.
* @see <a href="https://grub.gibibit.com/New_font_format">Source</a>
*/
type Grub2Font struct {
Magic []byte
Sections []*Grub2Font_Section
_io *kaitai.Stream
_root *Grub2Font
_parent kaitai.Struct
}
func NewGrub2Font() *Grub2Font {
return &Grub2Font{
}
}
func (this Grub2Font) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font) Read(io *kaitai.Stream, parent kaitai.Struct, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp1, err := this._io.ReadBytes(int(12))
if err != nil {
return err
}
tmp1 = tmp1
this.Magic = tmp1
if !(bytes.Equal(this.Magic, []uint8{70, 73, 76, 69, 0, 0, 0, 4, 80, 70, 70, 50})) {
return kaitai.NewValidationNotEqualError([]uint8{70, 73, 76, 69, 0, 0, 0, 4, 80, 70, 70, 50}, this.Magic, this._io, "/seq/0")
}
for i := 1;; i++ {
tmp2 := NewGrub2Font_Section()
err = tmp2.Read(this._io, this, this._root)
if err != nil {
return err
}
_it := tmp2
this.Sections = append(this.Sections, _it)
if _it.SectionType == "DATA" {
break
}
}
return err
}
/**
* The "DATA" section acts as a terminator. The documentation says:
* "A marker that indicates the remainder of the file is data accessed
* via the character index (CHIX) section. When reading this font file,
* the rest of the file can be ignored when scanning the sections."
*/
type Grub2Font_AsceSection struct {
AscentInPixels uint16
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_AsceSection() *Grub2Font_AsceSection {
return &Grub2Font_AsceSection{
}
}
func (this Grub2Font_AsceSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_AsceSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp3, err := this._io.ReadU2be()
if err != nil {
return err
}
this.AscentInPixels = uint16(tmp3)
return err
}
type Grub2Font_ChixSection struct {
Characters []*Grub2Font_ChixSection_Character
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_ChixSection() *Grub2Font_ChixSection {
return &Grub2Font_ChixSection{
}
}
func (this Grub2Font_ChixSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_ChixSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
for i := 0;; i++ {
tmp4, err := this._io.EOF()
if err != nil {
return err
}
if tmp4 {
break
}
tmp5 := NewGrub2Font_ChixSection_Character()
err = tmp5.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Characters = append(this.Characters, tmp5)
}
return err
}
type Grub2Font_ChixSection_Character struct {
CodePoint uint32
Flags uint8
OfsDefinition uint32
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_ChixSection
_f_definition bool
definition *Grub2Font_ChixSection_CharacterDefinition
}
func NewGrub2Font_ChixSection_Character() *Grub2Font_ChixSection_Character {
return &Grub2Font_ChixSection_Character{
}
}
func (this Grub2Font_ChixSection_Character) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_ChixSection_Character) Read(io *kaitai.Stream, parent *Grub2Font_ChixSection, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp6, err := this._io.ReadU4be()
if err != nil {
return err
}
this.CodePoint = uint32(tmp6)
tmp7, err := this._io.ReadU1()
if err != nil {
return err
}
this.Flags = tmp7
tmp8, err := this._io.ReadU4be()
if err != nil {
return err
}
this.OfsDefinition = uint32(tmp8)
return err
}
func (this *Grub2Font_ChixSection_Character) Definition() (v *Grub2Font_ChixSection_CharacterDefinition, err error) {
if (this._f_definition) {
return this.definition, nil
}
this._f_definition = true
thisIo := this._root._io
_pos, err := thisIo.Pos()
if err != nil {
return nil, err
}
_, err = thisIo.Seek(int64(this.OfsDefinition), io.SeekStart)
if err != nil {
return nil, err
}
tmp9 := NewGrub2Font_ChixSection_CharacterDefinition()
err = tmp9.Read(thisIo, this, this._root)
if err != nil {
return nil, err
}
this.definition = tmp9
_, err = thisIo.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
return this.definition, nil
}
/**
* Unicode code point
*/
type Grub2Font_ChixSection_CharacterDefinition struct {
Width uint16
Height uint16
XOffset int16
YOffset int16
DeviceWidth int16
BitmapData []byte
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_ChixSection_Character
}
func NewGrub2Font_ChixSection_CharacterDefinition() *Grub2Font_ChixSection_CharacterDefinition {
return &Grub2Font_ChixSection_CharacterDefinition{
}
}
func (this Grub2Font_ChixSection_CharacterDefinition) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_ChixSection_CharacterDefinition) Read(io *kaitai.Stream, parent *Grub2Font_ChixSection_Character, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp10, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Width = uint16(tmp10)
tmp11, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Height = uint16(tmp11)
tmp12, err := this._io.ReadS2be()
if err != nil {
return err
}
this.XOffset = int16(tmp12)
tmp13, err := this._io.ReadS2be()
if err != nil {
return err
}
this.YOffset = int16(tmp13)
tmp14, err := this._io.ReadS2be()
if err != nil {
return err
}
this.DeviceWidth = int16(tmp14)
tmp15, err := this._io.ReadBytes(int((this.Width * this.Height + 7) / 8))
if err != nil {
return err
}
tmp15 = tmp15
this.BitmapData = tmp15
return err
}
/**
* A two-dimensional bitmap, one bit per pixel. It is organized as
* row-major, top-down, left-to-right. The most significant bit of
* each byte corresponds to the leftmost or uppermost pixel from all
* bits of the byte. If a bit is set (1, `true`), the pixel is set to
* the font color, if a bit is clear (0, `false`), the pixel is
* transparent.
*
* Rows are **not** padded to byte boundaries (i.e., a
* single byte may contain bits belonging to multiple rows). The last
* byte of the bitmap _is_ padded with zero bits at all unused least
* significant bit positions so that the bitmap ends on a byte
* boundary.
*/
type Grub2Font_DescSection struct {
DescentInPixels uint16
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_DescSection() *Grub2Font_DescSection {
return &Grub2Font_DescSection{
}
}
func (this Grub2Font_DescSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_DescSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp16, err := this._io.ReadU2be()
if err != nil {
return err
}
this.DescentInPixels = uint16(tmp16)
return err
}
type Grub2Font_FamiSection struct {
FontFamilyName string
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_FamiSection() *Grub2Font_FamiSection {
return &Grub2Font_FamiSection{
}
}
func (this Grub2Font_FamiSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_FamiSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp17, err := this._io.ReadBytesTerm(0, false, true, true)
if err != nil {
return err
}
this.FontFamilyName = string(tmp17)
return err
}
type Grub2Font_MaxhSection struct {
MaximumCharacterHeight uint16
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_MaxhSection() *Grub2Font_MaxhSection {
return &Grub2Font_MaxhSection{
}
}
func (this Grub2Font_MaxhSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_MaxhSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp18, err := this._io.ReadU2be()
if err != nil {
return err
}
this.MaximumCharacterHeight = uint16(tmp18)
return err
}
type Grub2Font_MaxwSection struct {
MaximumCharacterWidth uint16
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_MaxwSection() *Grub2Font_MaxwSection {
return &Grub2Font_MaxwSection{
}
}
func (this Grub2Font_MaxwSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_MaxwSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp19, err := this._io.ReadU2be()
if err != nil {
return err
}
this.MaximumCharacterWidth = uint16(tmp19)
return err
}
type Grub2Font_NameSection struct {
FontName string
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_NameSection() *Grub2Font_NameSection {
return &Grub2Font_NameSection{
}
}
func (this Grub2Font_NameSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_NameSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp20, err := this._io.ReadBytesTerm(0, false, true, true)
if err != nil {
return err
}
this.FontName = string(tmp20)
return err
}
type Grub2Font_PtszSection struct {
FontPointSize uint16
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_PtszSection() *Grub2Font_PtszSection {
return &Grub2Font_PtszSection{
}
}
func (this Grub2Font_PtszSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_PtszSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp21, err := this._io.ReadU2be()
if err != nil {
return err
}
this.FontPointSize = uint16(tmp21)
return err
}
type Grub2Font_Section struct {
SectionType string
LenBody uint32
Body interface{}
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font
_raw_Body []byte
}
func NewGrub2Font_Section() *Grub2Font_Section {
return &Grub2Font_Section{
}
}
func (this Grub2Font_Section) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_Section) Read(io *kaitai.Stream, parent *Grub2Font, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp22, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp22 = tmp22
this.SectionType = string(tmp22)
tmp23, err := this._io.ReadU4be()
if err != nil {
return err
}
this.LenBody = uint32(tmp23)
if (this.SectionType != "DATA") {
switch (this.SectionType) {
case "ASCE":
tmp24, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp24 = tmp24
this._raw_Body = tmp24
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp25 := NewGrub2Font_AsceSection()
err = tmp25.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp25
case "CHIX":
tmp26, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp26 = tmp26
this._raw_Body = tmp26
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp27 := NewGrub2Font_ChixSection()
err = tmp27.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp27
case "DESC":
tmp28, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp28 = tmp28
this._raw_Body = tmp28
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp29 := NewGrub2Font_DescSection()
err = tmp29.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp29
case "FAMI":
tmp30, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp30 = tmp30
this._raw_Body = tmp30
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp31 := NewGrub2Font_FamiSection()
err = tmp31.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp31
case "MAXH":
tmp32, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp32 = tmp32
this._raw_Body = tmp32
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp33 := NewGrub2Font_MaxhSection()
err = tmp33.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp33
case "MAXW":
tmp34, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp34 = tmp34
this._raw_Body = tmp34
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp35 := NewGrub2Font_MaxwSection()
err = tmp35.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp35
case "NAME":
tmp36, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp36 = tmp36
this._raw_Body = tmp36
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp37 := NewGrub2Font_NameSection()
err = tmp37.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp37
case "PTSZ":
tmp38, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp38 = tmp38
this._raw_Body = tmp38
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp39 := NewGrub2Font_PtszSection()
err = tmp39.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp39
case "SLAN":
tmp40, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp40 = tmp40
this._raw_Body = tmp40
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp41 := NewGrub2Font_SlanSection()
err = tmp41.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp41
case "WEIG":
tmp42, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp42 = tmp42
this._raw_Body = tmp42
_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
tmp43 := NewGrub2Font_WeigSection()
err = tmp43.Read(_io__raw_Body, this, this._root)
if err != nil {
return err
}
this.Body = tmp43
default:
tmp44, err := this._io.ReadBytes(int(this.LenBody))
if err != nil {
return err
}
tmp44 = tmp44
this._raw_Body = tmp44
}
}
return err
}
/**
* Should be set to `0xFFFF_FFFF` for `section_type != "DATA"`
*/
type Grub2Font_SlanSection struct {
FontSlant string
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_SlanSection() *Grub2Font_SlanSection {
return &Grub2Font_SlanSection{
}
}
func (this Grub2Font_SlanSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_SlanSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp45, err := this._io.ReadBytesTerm(0, false, true, true)
if err != nil {
return err
}
this.FontSlant = string(tmp45)
return err
}
type Grub2Font_WeigSection struct {
FontWeight string
_io *kaitai.Stream
_root *Grub2Font
_parent *Grub2Font_Section
}
func NewGrub2Font_WeigSection() *Grub2Font_WeigSection {
return &Grub2Font_WeigSection{
}
}
func (this Grub2Font_WeigSection) IO_() *kaitai.Stream {
return this._io
}
func (this *Grub2Font_WeigSection) Read(io *kaitai.Stream, parent *Grub2Font_Section, root *Grub2Font) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp46, err := this._io.ReadBytesTerm(0, false, true, true)
if err != nil {
return err
}
this.FontWeight = string(tmp46)
return err
}