xref: /plan9/sys/src/cmd/disk/9660/boot.c (revision f7db61556a577f91350f05658e9c0724969b02c3)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <libsec.h>
5 
6 #include "iso9660.h"
7 
8 /* FreeBSD 4.5 installation CD for reference
9 g% cdsector 17 | xd -b
10 1+0 records in
11 1+0 records out
12 0000000  00 	- volume descriptor type (0)
13          43 44 30 30 31     - "CD001"
14          01     - volume descriptor version (1)
15          45 4c 20 54 4f 52 49 54 4f
16 0000010  20 53 50 45 43 49 46 49 43 41 54 49 4f 4e 00 00
17 0000020  00 00 00 00 00 00 00 - 7-39 boot system identifier
18 "EL TORITO SPECIFICATION"
19 
20                               00 00 00 00 00 00 00 00 00
21 0000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
22 0000040  00 00 00 00 00 00 00 - 39-71 boot identifier
23 
24 boot system use:
25 
26 absolute pointer to the boot catalog??
27 
28                               4d 0c 00 00 00 00 00 00 00
29 0000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30 0000580  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
31 0000590  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
32 00005a0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
33 g% cdsector 3149 | xd -b	# 0x0c4d
34 1+0 records in
35 1+0 records out
36 0000000  01 	- header (1)
37             00  - platform id (0 = 0x86)
38                00 00 - reserved 0
39                      00 00 00 00 00 00 00 00 00 00 00 00
40 0000010  00 00 00 00 00 00 00 00 00 00 00 00 - id string
41                                              aa 55 - checksum
42                                                     55 aa - magic
43 
44 0000020  88    - 88 = bootable
45             03   - 3 = 2.88MB diskette
46                00 00 - load segment 0 means default 0x7C0
47                      00  - system type (byte 5 of boot image)
48                         00 - unused (0)
49                            01 00 - 512-byte sector count for initial load
50                                  4e 0c 00 00 - ptr to virtual disk
51                                              00 00 00 00
52 0000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
53 0000040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
54 0000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
55 0000060  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
56 g% cdsector `{h2d 0c4e} | xd -b
57 1+0 records in
58 1+0 records out
59 0000000  eb 3c 00 00 00 00 00 00 00 00 00 00 02 00 00 00
60 0000010  00 00 00 00 00 00 00 00 12 00 02 00 00 00 00 00
61 0000020  00 00 00 00 00 16 1f 66 6a 00 51 50 06 53
62                                           31 c0
63 
64 FREEBSD
65 0000000  eb 3c 00 00 00 00 00 00 00 00 00 00 02 00 00 00
66 0000010  00 00 00 00 00 00 00 00 12 00 02 00 00 00 00 00
67 0000020  00 00 00 00 00 16 1f 66 6a 00 51 50 06 53
68                                           31 c0
69 
70 DOS 5
71 0000000  eb 3c 90 4d 53 44 4f 53 35 2e 30 00 02 01 01 00
72 0000010  02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00
73 0000020  00 00 00 00 00 00 29 6a 2c e0 16 4e 4f 20 4e 41
74 0000030  4d 45 20 20 20 20 46 41 54 31 32 20 20 20 fa 33
75 0000040  c0 8e d0 bc 00 7c 16 07 bb 78 00 36 c5 37 1e 56
76 0000050  16 53 bf 3e 7c b9 0b 00 fc f3 a4 06 1f c6 45 fe
77 0000060  0f 8b 0e 18 7c 88 4d f9 89 47 02 c7 07 3e 7c fb
78 0000070  cd 13 72 79 33 c0 39 06 13 7c 74 08 8b 0e 13 7c
79 0000080  89 0e 20 7c a0 10 7c f7 26 16 7c 03 06 1c 7c 13
80 0000090  16 1e 7c 03 06 0e 7c 83 d2 00 a3 50 7c 89 16 52
81 00000a0  7c a3 49 7c 89 16 4b 7c b8 20 00 f7 26 11 7c 8b
82 
83 NDISK
84 0000000  eb 3c 90 50 6c 61 6e 39 2e 30 30 00 02 01 01 00
85 0000010  02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00
86 0000020  40 0b 00 00 00 00 29 13 00 00 00 43 59 4c 49 4e
87 0000030  44 52 49 43 41 4c 46 41 54 31 32 20 20 20 fa 31
88 0000040  c0 8e d0 8e d8 8e c0 bc ec 7b 89 e5 88 56 12 fb
89 0000050  be ea 7d bf 90 7d ff d7 bf 82 7d ff d7 8b 06 27
90 0000060  7c 8b 16 29 7c bb 00 7e bf 2c 7d ff d7 bb 10 00
91 
92 PBSDISK
93 0000000  eb 3c 90 50 6c 61 6e 39 2e 30 30 00 02 01 01 00
94 0000010  02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00
95 0000020  40 0b 00 00 00 00 29 13 00 00 00 43 59 4c 49 4e
96 0000030  44 52 49 43 41 4c 46 41 54 31 32 20 20 20 fa 31
97 0000040  c0 8e d0 8e d8 8e c0 bc f8 7b 89 e5 88 56 00 fb
98 0000050  be f8 7d bf 00 7d ff d7 bf df 7c ff d7 8b 06 27
99 0000060  7c 8b 16 29 7c bb 00 7e bf 89 7c ff d7 bf fb 7c
100 */
101 
102 void
Cputbootvol(Cdimg * cd)103 Cputbootvol(Cdimg *cd)
104 {
105 	Cputc(cd, 0x00);
106 	Cputs(cd, "CD001", 5);
107 	Cputc(cd, 0x01);
108 	Cputs(cd, "EL TORITO SPECIFICATION", 2+1+6+1+13);
109 	Crepeat(cd, 0, 2+16+16+7);
110 	cd->bootcatptr = Cwoffset(cd);
111 	Cpadblock(cd);
112 }
113 
114 void
Cupdatebootvol(Cdimg * cd)115 Cupdatebootvol(Cdimg *cd)
116 {
117 	uvlong o;
118 
119 	o = Cwoffset(cd);
120 	Cwseek(cd, cd->bootcatptr);
121 	Cputnl(cd, cd->bootcatblock, 4);
122 	Cwseek(cd, o);
123 }
124 
125 void
Cputbootcat(Cdimg * cd)126 Cputbootcat(Cdimg *cd)
127 {
128 	cd->bootcatblock = Cwoffset(cd) / Blocksize;
129 	Cputc(cd, 0x01);
130 	Cputc(cd, 0x00);
131 	Cputc(cd, 0x00);
132 	Cputc(cd, 0x00);
133 	Crepeat(cd, 0, 12+12);
134 
135 	/*
136 	 * either the checksum doesn't include the header word
137 	 * or it just doesn't matter.
138 	 */
139 	Cputc(cd, 0xAA);
140 	Cputc(cd, 0x55);
141 	Cputc(cd, 0x55);
142 	Cputc(cd, 0xAA);
143 
144 	cd->bootimageptr = Cwoffset(cd);
145 	Cpadblock(cd);
146 }
147 
148 enum {
149 	Emusectsz	= 512,		/* bytes per emulated sector */
150 };
151 
152 void
Cupdatebootcat(Cdimg * cd)153 Cupdatebootcat(Cdimg *cd)
154 {
155 	uvlong o;
156 	int n;
157 
158 	if(cd->bootdirec == nil)
159 		return;
160 
161 	o = Cwoffset(cd);
162 	Cwseek(cd, cd->bootimageptr);
163 	Cputc(cd, 0x88);
164 
165 	if(cd->flags & CDbootnoemu)
166 		Cputc(cd, 0);			/* no disk emulation */
167 	else
168 		switch(cd->bootdirec->length){
169 		default:
170 			fprint(2, "warning: boot image is not 1.44MB or 2.88MB; "
171 				"pretending 1.44MB\n");
172 			/* fall through */
173 		case 1440*1024:
174 			Cputc(cd, 0x02);	/* 1.44MB disk */
175 			break;
176 		case 2880*1024:
177 			Cputc(cd, 0x03);	/* 2.88MB disk */
178 			break;
179 		}
180 	Cputnl(cd, 0, 2);	/* load segment */
181 	Cputc(cd, 0);	/* system type */
182 	Cputc(cd, 0);	/* unused */
183 
184 	n = 1;
185 	if(cd->flags & CDbootnoemu){
186 		n = (cd->bootdirec->length + Emusectsz - 1) / Emusectsz;
187 		if(n > 4){
188 			fprint(2, "warning: boot image too big; "
189 				"will only load the first 2K\n");
190 			n = 4;
191 		}
192 	}
193 	Cputnl(cd, n, 2);	/* Emusectsz-byte sector count for load */
194 	Cputnl(cd, cd->bootdirec->block, 4);	/* ptr to disk image */
195 	Cwseek(cd, o);
196 }
197 
198 void
Cfillpbs(Cdimg * cd)199 Cfillpbs(Cdimg *cd)
200 {
201 	uvlong o;
202 	int n;
203 
204 	if(cd->bootdirec == nil || cd->loaderdirec == nil)
205 		return;
206 	o = Cwoffset(cd);
207 	Cwseek(cd, 3 + cd->bootdirec->block * Blocksize); /* jmp over magic */
208 
209 	Cputnl(cd, cd->loaderdirec->block, 4);		/* ptr to loader */
210 	n = (cd->loaderdirec->length + Blocksize - 1) / Blocksize;
211 	Cputnl(cd, n, 4);				/* loader size */
212 	Cputnl(cd, Blocksize, 4);			/* loader size */
213 	Cwseek(cd, o);
214 }
215 
216 void
findbootimage(Cdimg * cd,Direc * root)217 findbootimage(Cdimg *cd, Direc *root)
218 {
219 	Direc *d;
220 	d = walkdirec(root, cd->bootimage);
221 	if(d == nil){
222 		fprint(2, "warning: did not encounter boot image\n");
223 		return;
224 	}
225 
226 	cd->bootdirec = d;
227 }
228 
229 void
findloader(Cdimg * cd,Direc * root)230 findloader(Cdimg *cd, Direc *root)
231 {
232 	Direc *d;
233 
234 	d = walkdirec(root, cd->loader);
235 	if(d == nil){
236 		fprint(2, "warning: did not encounter boot loader\n");
237 		return;
238 	}
239 	cd->loaderdirec = d;
240 }
241