1/* This utility makes a bootblock suitable for the SRM console/miniloader */
2
3/* Usage:
4 *	mkbb <device> <lxboot>
5 *
6 * Where <device> is the name of the device to install the bootblock on,
7 * and <lxboot> is the name of a bootblock to merge in.  This bootblock
8 * contains the offset and size of the bootloader.  It must be exactly
9 * 512 bytes long.
10 */
11
12#include <fcntl.h>
13#include <unistd.h>
14#include <stdio.h>
15
16/* Minimal definition of disklabel, so we don't have to include
17 * asm/disklabel.h (confuses make)
18 */
19#ifndef MAXPARTITIONS
20#define MAXPARTITIONS   8                       /* max. # of partitions */
21#endif
22
23#ifndef u8
24#define u8 unsigned char
25#endif
26
27#ifndef u16
28#define u16 unsigned short
29#endif
30
31#ifndef u32
32#define u32 unsigned int
33#endif
34
35struct disklabel {
36    u32	d_magic;				/* must be DISKLABELMAGIC */
37    u16	d_type, d_subtype;
38    u8	d_typename[16];
39    u8	d_packname[16];
40    u32	d_secsize;
41    u32	d_nsectors;
42    u32	d_ntracks;
43    u32	d_ncylinders;
44    u32	d_secpercyl;
45    u32	d_secprtunit;
46    u16	d_sparespertrack;
47    u16	d_sparespercyl;
48    u32	d_acylinders;
49    u16	d_rpm, d_interleave, d_trackskew, d_cylskew;
50    u32	d_headswitch, d_trkseek, d_flags;
51    u32	d_drivedata[5];
52    u32	d_spare[5];
53    u32	d_magic2;				/* must be DISKLABELMAGIC */
54    u16	d_checksum;
55    u16	d_npartitions;
56    u32	d_bbsize, d_sbsize;
57    struct d_partition {
58	u32	p_size;
59	u32	p_offset;
60	u32	p_fsize;
61	u8	p_fstype;
62	u8	p_frag;
63	u16	p_cpg;
64    } d_partitions[MAXPARTITIONS];
65};
66
67
68typedef union __bootblock {
69    struct {
70        char			__pad1[64];
71        struct disklabel	__label;
72    } __u1;
73    struct {
74	unsigned long		__pad2[63];
75	unsigned long		__checksum;
76    } __u2;
77    char		bootblock_bytes[512];
78    unsigned long	bootblock_quadwords[64];
79} bootblock;
80
81#define	bootblock_label		__u1.__label
82#define bootblock_checksum	__u2.__checksum
83
84int main(int argc, char ** argv)
85{
86    bootblock		bootblock_from_disk;
87    bootblock		bootloader_image;
88    int			dev, fd;
89    int			i;
90    int			nread;
91
92    /* Make sure of the arg count */
93    if(argc != 3) {
94	fprintf(stderr, "Usage: %s device lxboot\n", argv[0]);
95	exit(0);
96    }
97
98    /* First, open the device and make sure it's accessible */
99    dev = open(argv[1], O_RDWR);
100    if(dev < 0) {
101	perror(argv[1]);
102	exit(0);
103    }
104
105    /* Now open the lxboot and make sure it's reasonable */
106    fd = open(argv[2], O_RDONLY);
107    if(fd < 0) {
108	perror(argv[2]);
109	close(dev);
110	exit(0);
111    }
112
113    /* Read in the lxboot */
114    nread = read(fd, &bootloader_image, sizeof(bootblock));
115    if(nread != sizeof(bootblock)) {
116	perror("lxboot read");
117	fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread);
118	exit(0);
119    }
120
121    /* Read in the bootblock from disk. */
122    nread = read(dev, &bootblock_from_disk, sizeof(bootblock));
123    if(nread != sizeof(bootblock)) {
124	perror("bootblock read");
125	fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread);
126	exit(0);
127    }
128
129    /* Swap the bootblock's disklabel into the bootloader */
130    bootloader_image.bootblock_label = bootblock_from_disk.bootblock_label;
131
132    /* Calculate the bootblock checksum */
133    bootloader_image.bootblock_checksum = 0;
134    for(i = 0; i < 63; i++) {
135	bootloader_image.bootblock_checksum +=
136			bootloader_image.bootblock_quadwords[i];
137    }
138
139    /* Write the whole thing out! */
140    lseek(dev, 0L, SEEK_SET);
141    if(write(dev, &bootloader_image, sizeof(bootblock)) != sizeof(bootblock)) {
142	perror("bootblock write");
143	exit(0);
144    }
145
146    close(fd);
147    close(dev);
148    exit(0);
149}
150