xref: /plan9/sys/src/cmd/disk/9660/boot.c (revision f7db61556a577f91350f05658e9c0724969b02c3)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <libsec.h>
59a747e4fSDavid du Colombier 
69a747e4fSDavid du Colombier #include "iso9660.h"
79a747e4fSDavid du Colombier 
89a747e4fSDavid du Colombier /* FreeBSD 4.5 installation CD for reference
99a747e4fSDavid du Colombier g% cdsector 17 | xd -b
109a747e4fSDavid du Colombier 1+0 records in
119a747e4fSDavid du Colombier 1+0 records out
129a747e4fSDavid du Colombier 0000000  00 	- volume descriptor type (0)
139a747e4fSDavid du Colombier          43 44 30 30 31     - "CD001"
149a747e4fSDavid du Colombier          01     - volume descriptor version (1)
159a747e4fSDavid du Colombier          45 4c 20 54 4f 52 49 54 4f
169a747e4fSDavid du Colombier 0000010  20 53 50 45 43 49 46 49 43 41 54 49 4f 4e 00 00
179a747e4fSDavid du Colombier 0000020  00 00 00 00 00 00 00 - 7-39 boot system identifier
189a747e4fSDavid du Colombier "EL TORITO SPECIFICATION"
199a747e4fSDavid du Colombier 
209a747e4fSDavid du Colombier                               00 00 00 00 00 00 00 00 00
219a747e4fSDavid du Colombier 0000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
229a747e4fSDavid du Colombier 0000040  00 00 00 00 00 00 00 - 39-71 boot identifier
239a747e4fSDavid du Colombier 
249a747e4fSDavid du Colombier boot system use:
259a747e4fSDavid du Colombier 
269a747e4fSDavid du Colombier absolute pointer to the boot catalog??
279a747e4fSDavid du Colombier 
289a747e4fSDavid du Colombier                               4d 0c 00 00 00 00 00 00 00
299a747e4fSDavid du Colombier 0000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
309a747e4fSDavid du Colombier 0000580  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
319a747e4fSDavid du Colombier 0000590  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
329a747e4fSDavid du Colombier 00005a0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
339a747e4fSDavid du Colombier g% cdsector 3149 | xd -b	# 0x0c4d
349a747e4fSDavid du Colombier 1+0 records in
359a747e4fSDavid du Colombier 1+0 records out
369a747e4fSDavid du Colombier 0000000  01 	- header (1)
379a747e4fSDavid du Colombier             00  - platform id (0 = 0x86)
389a747e4fSDavid du Colombier                00 00 - reserved 0
399a747e4fSDavid du Colombier                      00 00 00 00 00 00 00 00 00 00 00 00
409a747e4fSDavid du Colombier 0000010  00 00 00 00 00 00 00 00 00 00 00 00 - id string
419a747e4fSDavid du Colombier                                              aa 55 - checksum
429a747e4fSDavid du Colombier                                                     55 aa - magic
439a747e4fSDavid du Colombier 
449a747e4fSDavid du Colombier 0000020  88    - 88 = bootable
459a747e4fSDavid du Colombier             03   - 3 = 2.88MB diskette
469a747e4fSDavid du Colombier                00 00 - load segment 0 means default 0x7C0
479a747e4fSDavid du Colombier                      00  - system type (byte 5 of boot image)
489a747e4fSDavid du Colombier                         00 - unused (0)
499a747e4fSDavid du Colombier                            01 00 - 512-byte sector count for initial load
509a747e4fSDavid du Colombier                                  4e 0c 00 00 - ptr to virtual disk
519a747e4fSDavid du Colombier                                              00 00 00 00
529a747e4fSDavid du Colombier 0000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
539a747e4fSDavid du Colombier 0000040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
549a747e4fSDavid du Colombier 0000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
559a747e4fSDavid du Colombier 0000060  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
569a747e4fSDavid du Colombier g% cdsector `{h2d 0c4e} | xd -b
579a747e4fSDavid du Colombier 1+0 records in
589a747e4fSDavid du Colombier 1+0 records out
599a747e4fSDavid du Colombier 0000000  eb 3c 00 00 00 00 00 00 00 00 00 00 02 00 00 00
609a747e4fSDavid du Colombier 0000010  00 00 00 00 00 00 00 00 12 00 02 00 00 00 00 00
619a747e4fSDavid du Colombier 0000020  00 00 00 00 00 16 1f 66 6a 00 51 50 06 53
629a747e4fSDavid du Colombier                                           31 c0
639a747e4fSDavid du Colombier 
649a747e4fSDavid du Colombier FREEBSD
659a747e4fSDavid du Colombier 0000000  eb 3c 00 00 00 00 00 00 00 00 00 00 02 00 00 00
669a747e4fSDavid du Colombier 0000010  00 00 00 00 00 00 00 00 12 00 02 00 00 00 00 00
679a747e4fSDavid du Colombier 0000020  00 00 00 00 00 16 1f 66 6a 00 51 50 06 53
689a747e4fSDavid du Colombier                                           31 c0
699a747e4fSDavid du Colombier 
709a747e4fSDavid du Colombier DOS 5
719a747e4fSDavid du Colombier 0000000  eb 3c 90 4d 53 44 4f 53 35 2e 30 00 02 01 01 00
729a747e4fSDavid du Colombier 0000010  02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00
739a747e4fSDavid du Colombier 0000020  00 00 00 00 00 00 29 6a 2c e0 16 4e 4f 20 4e 41
749a747e4fSDavid du Colombier 0000030  4d 45 20 20 20 20 46 41 54 31 32 20 20 20 fa 33
759a747e4fSDavid du Colombier 0000040  c0 8e d0 bc 00 7c 16 07 bb 78 00 36 c5 37 1e 56
769a747e4fSDavid du Colombier 0000050  16 53 bf 3e 7c b9 0b 00 fc f3 a4 06 1f c6 45 fe
779a747e4fSDavid du Colombier 0000060  0f 8b 0e 18 7c 88 4d f9 89 47 02 c7 07 3e 7c fb
789a747e4fSDavid du Colombier 0000070  cd 13 72 79 33 c0 39 06 13 7c 74 08 8b 0e 13 7c
799a747e4fSDavid du Colombier 0000080  89 0e 20 7c a0 10 7c f7 26 16 7c 03 06 1c 7c 13
809a747e4fSDavid du Colombier 0000090  16 1e 7c 03 06 0e 7c 83 d2 00 a3 50 7c 89 16 52
819a747e4fSDavid du Colombier 00000a0  7c a3 49 7c 89 16 4b 7c b8 20 00 f7 26 11 7c 8b
829a747e4fSDavid du Colombier 
839a747e4fSDavid du Colombier NDISK
849a747e4fSDavid du Colombier 0000000  eb 3c 90 50 6c 61 6e 39 2e 30 30 00 02 01 01 00
859a747e4fSDavid du Colombier 0000010  02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00
869a747e4fSDavid du Colombier 0000020  40 0b 00 00 00 00 29 13 00 00 00 43 59 4c 49 4e
879a747e4fSDavid du Colombier 0000030  44 52 49 43 41 4c 46 41 54 31 32 20 20 20 fa 31
889a747e4fSDavid du Colombier 0000040  c0 8e d0 8e d8 8e c0 bc ec 7b 89 e5 88 56 12 fb
899a747e4fSDavid du Colombier 0000050  be ea 7d bf 90 7d ff d7 bf 82 7d ff d7 8b 06 27
909a747e4fSDavid du Colombier 0000060  7c 8b 16 29 7c bb 00 7e bf 2c 7d ff d7 bb 10 00
919a747e4fSDavid du Colombier 
929a747e4fSDavid du Colombier PBSDISK
939a747e4fSDavid du Colombier 0000000  eb 3c 90 50 6c 61 6e 39 2e 30 30 00 02 01 01 00
949a747e4fSDavid du Colombier 0000010  02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00
959a747e4fSDavid du Colombier 0000020  40 0b 00 00 00 00 29 13 00 00 00 43 59 4c 49 4e
969a747e4fSDavid du Colombier 0000030  44 52 49 43 41 4c 46 41 54 31 32 20 20 20 fa 31
979a747e4fSDavid du Colombier 0000040  c0 8e d0 8e d8 8e c0 bc f8 7b 89 e5 88 56 00 fb
989a747e4fSDavid du Colombier 0000050  be f8 7d bf 00 7d ff d7 bf df 7c ff d7 8b 06 27
999a747e4fSDavid du Colombier 0000060  7c 8b 16 29 7c bb 00 7e bf 89 7c ff d7 bf fb 7c
1009a747e4fSDavid du Colombier */
1019a747e4fSDavid du Colombier 
1029a747e4fSDavid du Colombier void
Cputbootvol(Cdimg * cd)1039a747e4fSDavid du Colombier Cputbootvol(Cdimg *cd)
1049a747e4fSDavid du Colombier {
1059a747e4fSDavid du Colombier 	Cputc(cd, 0x00);
1069a747e4fSDavid du Colombier 	Cputs(cd, "CD001", 5);
1079a747e4fSDavid du Colombier 	Cputc(cd, 0x01);
1089a747e4fSDavid du Colombier 	Cputs(cd, "EL TORITO SPECIFICATION", 2+1+6+1+13);
1099a747e4fSDavid du Colombier 	Crepeat(cd, 0, 2+16+16+7);
1109a747e4fSDavid du Colombier 	cd->bootcatptr = Cwoffset(cd);
1119a747e4fSDavid du Colombier 	Cpadblock(cd);
1129a747e4fSDavid du Colombier }
1139a747e4fSDavid du Colombier 
1149a747e4fSDavid du Colombier void
Cupdatebootvol(Cdimg * cd)1159a747e4fSDavid du Colombier Cupdatebootvol(Cdimg *cd)
1169a747e4fSDavid du Colombier {
11773ee67a1SDavid du Colombier 	uvlong o;
1189a747e4fSDavid du Colombier 
1199a747e4fSDavid du Colombier 	o = Cwoffset(cd);
1209a747e4fSDavid du Colombier 	Cwseek(cd, cd->bootcatptr);
1219a747e4fSDavid du Colombier 	Cputnl(cd, cd->bootcatblock, 4);
1229a747e4fSDavid du Colombier 	Cwseek(cd, o);
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier 
1259a747e4fSDavid du Colombier void
Cputbootcat(Cdimg * cd)1269a747e4fSDavid du Colombier Cputbootcat(Cdimg *cd)
1279a747e4fSDavid du Colombier {
1289a747e4fSDavid du Colombier 	cd->bootcatblock = Cwoffset(cd) / Blocksize;
1299a747e4fSDavid du Colombier 	Cputc(cd, 0x01);
1309a747e4fSDavid du Colombier 	Cputc(cd, 0x00);
1319a747e4fSDavid du Colombier 	Cputc(cd, 0x00);
1329a747e4fSDavid du Colombier 	Cputc(cd, 0x00);
1339a747e4fSDavid du Colombier 	Crepeat(cd, 0, 12+12);
1349a747e4fSDavid du Colombier 
1359a747e4fSDavid du Colombier 	/*
1369a747e4fSDavid du Colombier 	 * either the checksum doesn't include the header word
1379a747e4fSDavid du Colombier 	 * or it just doesn't matter.
1389a747e4fSDavid du Colombier 	 */
1399a747e4fSDavid du Colombier 	Cputc(cd, 0xAA);
1409a747e4fSDavid du Colombier 	Cputc(cd, 0x55);
1419a747e4fSDavid du Colombier 	Cputc(cd, 0x55);
1429a747e4fSDavid du Colombier 	Cputc(cd, 0xAA);
1439a747e4fSDavid du Colombier 
1449a747e4fSDavid du Colombier 	cd->bootimageptr = Cwoffset(cd);
1459a747e4fSDavid du Colombier 	Cpadblock(cd);
1469a747e4fSDavid du Colombier }
1479a747e4fSDavid du Colombier 
14843751f27SDavid du Colombier enum {
14943751f27SDavid du Colombier 	Emusectsz	= 512,		/* bytes per emulated sector */
15043751f27SDavid du Colombier };
15143751f27SDavid du Colombier 
1529a747e4fSDavid du Colombier void
Cupdatebootcat(Cdimg * cd)1539a747e4fSDavid du Colombier Cupdatebootcat(Cdimg *cd)
1549a747e4fSDavid du Colombier {
15573ee67a1SDavid du Colombier 	uvlong o;
15643751f27SDavid du Colombier 	int n;
1579a747e4fSDavid du Colombier 
1589a747e4fSDavid du Colombier 	if(cd->bootdirec == nil)
1599a747e4fSDavid du Colombier 		return;
1609a747e4fSDavid du Colombier 
1619a747e4fSDavid du Colombier 	o = Cwoffset(cd);
1629a747e4fSDavid du Colombier 	Cwseek(cd, cd->bootimageptr);
1639a747e4fSDavid du Colombier 	Cputc(cd, 0x88);
16443751f27SDavid du Colombier 
16543751f27SDavid du Colombier 	if(cd->flags & CDbootnoemu)
16643751f27SDavid du Colombier 		Cputc(cd, 0);			/* no disk emulation */
16743751f27SDavid du Colombier 	else
1689a747e4fSDavid du Colombier 		switch(cd->bootdirec->length){
1699a747e4fSDavid du Colombier 		default:
17043751f27SDavid du Colombier 			fprint(2, "warning: boot image is not 1.44MB or 2.88MB; "
17143751f27SDavid du Colombier 				"pretending 1.44MB\n");
17243751f27SDavid du Colombier 			/* fall through */
1739a747e4fSDavid du Colombier 		case 1440*1024:
1749a747e4fSDavid du Colombier 			Cputc(cd, 0x02);	/* 1.44MB disk */
1759a747e4fSDavid du Colombier 			break;
1769a747e4fSDavid du Colombier 		case 2880*1024:
1779a747e4fSDavid du Colombier 			Cputc(cd, 0x03);	/* 2.88MB disk */
1789a747e4fSDavid du Colombier 			break;
1799a747e4fSDavid du Colombier 		}
1809a747e4fSDavid du Colombier 	Cputnl(cd, 0, 2);	/* load segment */
1819a747e4fSDavid du Colombier 	Cputc(cd, 0);	/* system type */
1829a747e4fSDavid du Colombier 	Cputc(cd, 0);	/* unused */
18343751f27SDavid du Colombier 
18443751f27SDavid du Colombier 	n = 1;
18543751f27SDavid du Colombier 	if(cd->flags & CDbootnoemu){
18643751f27SDavid du Colombier 		n = (cd->bootdirec->length + Emusectsz - 1) / Emusectsz;
18743751f27SDavid du Colombier 		if(n > 4){
18843751f27SDavid du Colombier 			fprint(2, "warning: boot image too big; "
18943751f27SDavid du Colombier 				"will only load the first 2K\n");
19043751f27SDavid du Colombier 			n = 4;
19143751f27SDavid du Colombier 		}
19243751f27SDavid du Colombier 	}
19343751f27SDavid du Colombier 	Cputnl(cd, n, 2);	/* Emusectsz-byte sector count for load */
1949a747e4fSDavid du Colombier 	Cputnl(cd, cd->bootdirec->block, 4);	/* ptr to disk image */
1959a747e4fSDavid du Colombier 	Cwseek(cd, o);
1969a747e4fSDavid du Colombier }
1979a747e4fSDavid du Colombier 
1989a747e4fSDavid du Colombier void
Cfillpbs(Cdimg * cd)199*f7db6155SDavid du Colombier Cfillpbs(Cdimg *cd)
200*f7db6155SDavid du Colombier {
201*f7db6155SDavid du Colombier 	uvlong o;
202*f7db6155SDavid du Colombier 	int n;
203*f7db6155SDavid du Colombier 
204*f7db6155SDavid du Colombier 	if(cd->bootdirec == nil || cd->loaderdirec == nil)
205*f7db6155SDavid du Colombier 		return;
206*f7db6155SDavid du Colombier 	o = Cwoffset(cd);
207*f7db6155SDavid du Colombier 	Cwseek(cd, 3 + cd->bootdirec->block * Blocksize); /* jmp over magic */
208*f7db6155SDavid du Colombier 
209*f7db6155SDavid du Colombier 	Cputnl(cd, cd->loaderdirec->block, 4);		/* ptr to loader */
210*f7db6155SDavid du Colombier 	n = (cd->loaderdirec->length + Blocksize - 1) / Blocksize;
211*f7db6155SDavid du Colombier 	Cputnl(cd, n, 4);				/* loader size */
212*f7db6155SDavid du Colombier 	Cputnl(cd, Blocksize, 4);			/* loader size */
213*f7db6155SDavid du Colombier 	Cwseek(cd, o);
214*f7db6155SDavid du Colombier }
215*f7db6155SDavid du Colombier 
216*f7db6155SDavid du Colombier void
findbootimage(Cdimg * cd,Direc * root)2179a747e4fSDavid du Colombier findbootimage(Cdimg *cd, Direc *root)
2189a747e4fSDavid du Colombier {
2199a747e4fSDavid du Colombier 	Direc *d;
2209a747e4fSDavid du Colombier 	d = walkdirec(root, cd->bootimage);
2219a747e4fSDavid du Colombier 	if(d == nil){
2229a747e4fSDavid du Colombier 		fprint(2, "warning: did not encounter boot image\n");
2239a747e4fSDavid du Colombier 		return;
2249a747e4fSDavid du Colombier 	}
2259a747e4fSDavid du Colombier 
2269a747e4fSDavid du Colombier 	cd->bootdirec = d;
2279a747e4fSDavid du Colombier }
228*f7db6155SDavid du Colombier 
229*f7db6155SDavid du Colombier void
findloader(Cdimg * cd,Direc * root)230*f7db6155SDavid du Colombier findloader(Cdimg *cd, Direc *root)
231*f7db6155SDavid du Colombier {
232*f7db6155SDavid du Colombier 	Direc *d;
233*f7db6155SDavid du Colombier 
234*f7db6155SDavid du Colombier 	d = walkdirec(root, cd->loader);
235*f7db6155SDavid du Colombier 	if(d == nil){
236*f7db6155SDavid du Colombier 		fprint(2, "warning: did not encounter boot loader\n");
237*f7db6155SDavid du Colombier 		return;
238*f7db6155SDavid du Colombier 	}
239*f7db6155SDavid du Colombier 	cd->loaderdirec = d;
240*f7db6155SDavid du Colombier }
241