// SPDX-License-Identifier: GPL-2.0 /* This utility makes a bootblock suitable for the SRM console/miniloader */ /* Usage: * mkbb <device> <lxboot> * * Where <device> is the name of the device to install the bootblock on, * and <lxboot> is the name of a bootblock to merge in. This bootblock * contains the offset and size of the bootloader. It must be exactly * 512 bytes long. */ #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> /* Minimal definition of disklabel, so we don't have to include * asm/disklabel.h (confuses make) */ #ifndef MAXPARTITIONS #define MAXPARTITIONS 8 /* max. # of partitions */ #endif #ifndef u8 #define u8 unsigned char #endif #ifndef u16 #define u16 unsigned short #endif #ifndef u32 #define u32 unsigned int #endif struct disklabel { u32 d_magic; /* must be DISKLABELMAGIC */ u16 d_type, d_subtype; u8 d_typename[16]; u8 d_packname[16]; u32 d_secsize; u32 d_nsectors; u32 d_ntracks; u32 d_ncylinders; u32 d_secpercyl; u32 d_secprtunit; u16 d_sparespertrack; u16 d_sparespercyl; u32 d_acylinders; u16 d_rpm, d_interleave, d_trackskew, d_cylskew; u32 d_headswitch, d_trkseek, d_flags; u32 d_drivedata[5]; u32 d_spare[5]; u32 d_magic2; /* must be DISKLABELMAGIC */ u16 d_checksum; u16 d_npartitions; u32 d_bbsize, d_sbsize; struct d_partition { u32 p_size; u32 p_offset; u32 p_fsize; u8 p_fstype; u8 p_frag; u16 p_cpg; } d_partitions[MAXPARTITIONS]; }; typedef union __bootblock { struct { char __pad1[64]; struct disklabel __label; } __u1; struct { unsigned long __pad2[63]; unsigned long __checksum; } __u2; char bootblock_bytes[512]; unsigned long bootblock_quadwords[64]; } bootblock; #define bootblock_label __u1.__label #define bootblock_checksum __u2.__checksum int main(int argc, char ** argv) { bootblock bootblock_from_disk; bootblock bootloader_image; int dev, fd; int i; int nread; /* Make sure of the arg count */ if(argc != 3) { fprintf(stderr, "Usage: %s device lxboot\n", argv[0]); exit(0); } /* First, open the device and make sure it's accessible */ dev = open(argv[1], O_RDWR); if(dev < 0) { perror(argv[1]); exit(0); } /* Now open the lxboot and make sure it's reasonable */ fd = open(argv[2], O_RDONLY); if(fd < 0) { perror(argv[2]); close(dev); exit(0); } /* Read in the lxboot */ nread = read(fd, &bootloader_image, sizeof(bootblock)); if(nread != sizeof(bootblock)) { perror("lxboot read"); fprintf(stderr, "expected %zd, got %d\n", sizeof(bootblock), nread); exit(0); } /* Read in the bootblock from disk. */ nread = read(dev, &bootblock_from_disk, sizeof(bootblock)); if(nread != sizeof(bootblock)) { perror("bootblock read"); fprintf(stderr, "expected %zd, got %d\n", sizeof(bootblock), nread); exit(0); } /* Swap the bootblock's disklabel into the bootloader */ bootloader_image.bootblock_label = bootblock_from_disk.bootblock_label; /* Calculate the bootblock checksum */ bootloader_image.bootblock_checksum = 0; for(i = 0; i < 63; i++) { bootloader_image.bootblock_checksum += bootloader_image.bootblock_quadwords[i]; } /* Write the whole thing out! */ lseek(dev, 0L, SEEK_SET); if(write(dev, &bootloader_image, sizeof(bootblock)) != sizeof(bootblock)) { perror("bootblock write"); exit(0); } close(fd); close(dev); exit(0); }