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