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