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