/* mbr.pk - MBR (Master Boot Record) partition table.  */

/* Copyright (C) 2021, 2022, 2023 The poke authors */

/* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* set_endian(ENDIAN_LITTLE); */

type MBR_CHS =
  struct
  {
    byte head;
    struct byte
      {
        uint<2> cylinder_hi;
        uint<6> sector;
      } cs;
    byte cylinder_lo;
    computed uint<10> cylinder;

    method get_cylinder = uint<10>:
      {
        return cs.cylinder_hi ::: cylinder_lo;
      }
    method set_cylinder = (uint<10> c) void:
      {
        cs.cylinder_hi = c .>> 8;
        cylinder_lo = c;
      }
    method _print = void:
      {
        printf ("#<head=%u8d,sector=%u6d,cylinder=%u10d>",
                head, cs.sector, get_cylinder);
      }
  };

/* MBR Partition Table Entry (PTE)
 *
 *  Offset  Size (bytes)  Description
 *
 *  0x00    1             Drive attributes (bit 7 set = active or bootable)
 *  0x01    3             CHS Address of partition start
 *  0x04    1             Partition type
 *  0x05    3             CHS address of last partition sector
 *  0x08    4             LBA of partition start
 *  0x0C    4             Number of sectors in partition
 *
 * ref: https://wiki.osdev.org/MBR_(x86)
 */
type MBR_PTE =
  struct
  {
    struct byte
    {
      uint<1> active;  /* bootable */
      uint<7>;

      method _print = void:
        {
          printf "#<active=%u1d>", active;
        }
    } attr;
    MBR_CHS start_chs;
    byte part_type;  /* partition type*/
    MBR_CHS end_chs;
    uint32 lba;
    uint32 sector_count;
  };

/*
 *  Offset  Size (bytes)  Description
 *
 *  0x000   440           MBR Bootstrap (flat binary executable code)
 *  0x1B8   4             Optional "Unique Disk ID / Signature"
 *  0x1BC   2             Optional, reserved 0x0000
 *  0x1BE   16            First partition table entry
 *  0x1CE   16            Second partition table entry
 *  0x1DE   16            Third partition table entry
 *  0x1EE   16            Fourth partition table entry
 *  0x1FE   2             (0x55, 0xAA) "Valid bootsector" signature bytes
 *
 * ref: https://wiki.osdev.org/MBR_(x86)
 */
type MBR =
  struct
  {
    byte[440#B] bootstrap;
    uint32 signature;
    byte[2] reserved;
    MBR_PTE[4] pte;
    uint16 magic == 0xaa55UH;
  };
