18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* This utility makes a bootblock suitable for the SRM console/miniloader */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci/* Usage:
58c2ecf20Sopenharmony_ci *	mkbb <device> <lxboot>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Where <device> is the name of the device to install the bootblock on,
88c2ecf20Sopenharmony_ci * and <lxboot> is the name of a bootblock to merge in.  This bootblock
98c2ecf20Sopenharmony_ci * contains the offset and size of the bootloader.  It must be exactly
108c2ecf20Sopenharmony_ci * 512 bytes long.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <fcntl.h>
148c2ecf20Sopenharmony_ci#include <unistd.h>
158c2ecf20Sopenharmony_ci#include <stdlib.h>
168c2ecf20Sopenharmony_ci#include <stdio.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* Minimal definition of disklabel, so we don't have to include
198c2ecf20Sopenharmony_ci * asm/disklabel.h (confuses make)
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci#ifndef MAXPARTITIONS
228c2ecf20Sopenharmony_ci#define MAXPARTITIONS   8                       /* max. # of partitions */
238c2ecf20Sopenharmony_ci#endif
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#ifndef u8
268c2ecf20Sopenharmony_ci#define u8 unsigned char
278c2ecf20Sopenharmony_ci#endif
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#ifndef u16
308c2ecf20Sopenharmony_ci#define u16 unsigned short
318c2ecf20Sopenharmony_ci#endif
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#ifndef u32
348c2ecf20Sopenharmony_ci#define u32 unsigned int
358c2ecf20Sopenharmony_ci#endif
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistruct disklabel {
388c2ecf20Sopenharmony_ci    u32	d_magic;				/* must be DISKLABELMAGIC */
398c2ecf20Sopenharmony_ci    u16	d_type, d_subtype;
408c2ecf20Sopenharmony_ci    u8	d_typename[16];
418c2ecf20Sopenharmony_ci    u8	d_packname[16];
428c2ecf20Sopenharmony_ci    u32	d_secsize;
438c2ecf20Sopenharmony_ci    u32	d_nsectors;
448c2ecf20Sopenharmony_ci    u32	d_ntracks;
458c2ecf20Sopenharmony_ci    u32	d_ncylinders;
468c2ecf20Sopenharmony_ci    u32	d_secpercyl;
478c2ecf20Sopenharmony_ci    u32	d_secprtunit;
488c2ecf20Sopenharmony_ci    u16	d_sparespertrack;
498c2ecf20Sopenharmony_ci    u16	d_sparespercyl;
508c2ecf20Sopenharmony_ci    u32	d_acylinders;
518c2ecf20Sopenharmony_ci    u16	d_rpm, d_interleave, d_trackskew, d_cylskew;
528c2ecf20Sopenharmony_ci    u32	d_headswitch, d_trkseek, d_flags;
538c2ecf20Sopenharmony_ci    u32	d_drivedata[5];
548c2ecf20Sopenharmony_ci    u32	d_spare[5];
558c2ecf20Sopenharmony_ci    u32	d_magic2;				/* must be DISKLABELMAGIC */
568c2ecf20Sopenharmony_ci    u16	d_checksum;
578c2ecf20Sopenharmony_ci    u16	d_npartitions;
588c2ecf20Sopenharmony_ci    u32	d_bbsize, d_sbsize;
598c2ecf20Sopenharmony_ci    struct d_partition {
608c2ecf20Sopenharmony_ci	u32	p_size;
618c2ecf20Sopenharmony_ci	u32	p_offset;
628c2ecf20Sopenharmony_ci	u32	p_fsize;
638c2ecf20Sopenharmony_ci	u8	p_fstype;
648c2ecf20Sopenharmony_ci	u8	p_frag;
658c2ecf20Sopenharmony_ci	u16	p_cpg;
668c2ecf20Sopenharmony_ci    } d_partitions[MAXPARTITIONS];
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_citypedef union __bootblock {
718c2ecf20Sopenharmony_ci    struct {
728c2ecf20Sopenharmony_ci        char			__pad1[64];
738c2ecf20Sopenharmony_ci        struct disklabel	__label;
748c2ecf20Sopenharmony_ci    } __u1;
758c2ecf20Sopenharmony_ci    struct {
768c2ecf20Sopenharmony_ci	unsigned long		__pad2[63];
778c2ecf20Sopenharmony_ci	unsigned long		__checksum;
788c2ecf20Sopenharmony_ci    } __u2;
798c2ecf20Sopenharmony_ci    char		bootblock_bytes[512];
808c2ecf20Sopenharmony_ci    unsigned long	bootblock_quadwords[64];
818c2ecf20Sopenharmony_ci} bootblock;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#define	bootblock_label		__u1.__label
848c2ecf20Sopenharmony_ci#define bootblock_checksum	__u2.__checksum
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ciint main(int argc, char ** argv)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci    bootblock		bootblock_from_disk;
898c2ecf20Sopenharmony_ci    bootblock		bootloader_image;
908c2ecf20Sopenharmony_ci    int			dev, fd;
918c2ecf20Sopenharmony_ci    int			i;
928c2ecf20Sopenharmony_ci    int			nread;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci    /* Make sure of the arg count */
958c2ecf20Sopenharmony_ci    if(argc != 3) {
968c2ecf20Sopenharmony_ci	fprintf(stderr, "Usage: %s device lxboot\n", argv[0]);
978c2ecf20Sopenharmony_ci	exit(0);
988c2ecf20Sopenharmony_ci    }
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci    /* First, open the device and make sure it's accessible */
1018c2ecf20Sopenharmony_ci    dev = open(argv[1], O_RDWR);
1028c2ecf20Sopenharmony_ci    if(dev < 0) {
1038c2ecf20Sopenharmony_ci	perror(argv[1]);
1048c2ecf20Sopenharmony_ci	exit(0);
1058c2ecf20Sopenharmony_ci    }
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci    /* Now open the lxboot and make sure it's reasonable */
1088c2ecf20Sopenharmony_ci    fd = open(argv[2], O_RDONLY);
1098c2ecf20Sopenharmony_ci    if(fd < 0) {
1108c2ecf20Sopenharmony_ci	perror(argv[2]);
1118c2ecf20Sopenharmony_ci	close(dev);
1128c2ecf20Sopenharmony_ci	exit(0);
1138c2ecf20Sopenharmony_ci    }
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci    /* Read in the lxboot */
1168c2ecf20Sopenharmony_ci    nread = read(fd, &bootloader_image, sizeof(bootblock));
1178c2ecf20Sopenharmony_ci    if(nread != sizeof(bootblock)) {
1188c2ecf20Sopenharmony_ci	perror("lxboot read");
1198c2ecf20Sopenharmony_ci	fprintf(stderr, "expected %zd, got %d\n", sizeof(bootblock), nread);
1208c2ecf20Sopenharmony_ci	exit(0);
1218c2ecf20Sopenharmony_ci    }
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci    /* Read in the bootblock from disk. */
1248c2ecf20Sopenharmony_ci    nread = read(dev, &bootblock_from_disk, sizeof(bootblock));
1258c2ecf20Sopenharmony_ci    if(nread != sizeof(bootblock)) {
1268c2ecf20Sopenharmony_ci	perror("bootblock read");
1278c2ecf20Sopenharmony_ci	fprintf(stderr, "expected %zd, got %d\n", sizeof(bootblock), nread);
1288c2ecf20Sopenharmony_ci	exit(0);
1298c2ecf20Sopenharmony_ci    }
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci    /* Swap the bootblock's disklabel into the bootloader */
1328c2ecf20Sopenharmony_ci    bootloader_image.bootblock_label = bootblock_from_disk.bootblock_label;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci    /* Calculate the bootblock checksum */
1358c2ecf20Sopenharmony_ci    bootloader_image.bootblock_checksum = 0;
1368c2ecf20Sopenharmony_ci    for(i = 0; i < 63; i++) {
1378c2ecf20Sopenharmony_ci	bootloader_image.bootblock_checksum +=
1388c2ecf20Sopenharmony_ci			bootloader_image.bootblock_quadwords[i];
1398c2ecf20Sopenharmony_ci    }
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci    /* Write the whole thing out! */
1428c2ecf20Sopenharmony_ci    lseek(dev, 0L, SEEK_SET);
1438c2ecf20Sopenharmony_ci    if(write(dev, &bootloader_image, sizeof(bootblock)) != sizeof(bootblock)) {
1448c2ecf20Sopenharmony_ci	perror("bootblock write");
1458c2ecf20Sopenharmony_ci	exit(0);
1468c2ecf20Sopenharmony_ci    }
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci    close(fd);
1498c2ecf20Sopenharmony_ci    close(dev);
1508c2ecf20Sopenharmony_ci    exit(0);
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci
154