build-the-world.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. #!/usr/bin/python3
  2. import tarfile
  3. import glob
  4. import subprocess
  5. import array
  6. import struct
  7. import os
  8. def BuildKernel():
  9. kernel_c_sources = glob.glob("kernel/*.c") + glob.glob("kernel/*/*.c") + glob.glob("kernel/*/*/*.c")
  10. kernel_s_sources = glob.glob("kernel/*.S")
  11. cflags = "-O2 -std=c99 -finline-functions -ffreestanding -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -Wno-format -pedantic -fno-omit-frame-pointer -D_KERNEL_ -DKERNEL_GIT_TAG=master"
  12. for i in kernel_c_sources:
  13. cmd = "gcc {cflags} -nostdlib -g -c -o {obj} {src}".format(
  14. cflags=cflags,
  15. obj=i.replace('.c','.o'),
  16. src=i
  17. )
  18. print(cmd)
  19. subprocess.run(cmd, shell=True)
  20. for i in kernel_s_sources:
  21. cmd = "as -o {obj} {src}".format(
  22. obj=i.replace('.S','.o'),
  23. src=i
  24. )
  25. print(cmd)
  26. subprocess.run(cmd,shell=True)
  27. objects = [x.replace('.c','.o') for x in kernel_c_sources] + [x.replace('.S','.o') for x in kernel_s_sources if not x.endswith('symbols.S')]
  28. cmd = "gcc -T kernel/link.ld {cflags} -nostdlib -o .toaruos-kernel {objects} -lgcc".format(
  29. cflags=cflags,
  30. objects=' '.join(objects),
  31. )
  32. print(cmd)
  33. subprocess.run(cmd, shell=True)
  34. cmd = "nm -g .toaruos-kernel | generate_symbols.py > kernel/symbols.S"
  35. print(cmd)
  36. subprocess.run(cmd,shell=True)
  37. subprocess.run("rm .toaruos-kernel", shell=True)
  38. cmd = "as -o kernel/symbols.o kernel/symbols.S"
  39. print(cmd)
  40. subprocess.run(cmd,shell=True)
  41. cmd = "gcc -T kernel/link.ld {cflags} -nostdlib -o cdrom/kernel {objects} kernel/symbols.o -lgcc".format(
  42. cflags=cflags,
  43. objects=' '.join(objects),
  44. )
  45. print(cmd)
  46. subprocess.run(cmd, shell=True)
  47. def BuildModules():
  48. module_sources = glob.glob('modules/*.c')
  49. cflags = "-O2 -std=c99 -finline-functions -ffreestanding -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -Wno-format -pedantic -fno-omit-frame-pointer -D_KERNEL_ -DKERNEL_GIT_TAG=master"
  50. try:
  51. os.mkdir('cdrom/mod')
  52. except:
  53. pass
  54. for i in module_sources:
  55. cmd = "gcc {cflags} -nostdlib -g -c -o {obj} {src}".format(
  56. cflags=cflags,
  57. obj=i.replace('.c','.ko').replace('modules/','cdrom/mod/'),
  58. src=i
  59. )
  60. print(cmd)
  61. subprocess.run(cmd, shell=True)
  62. class Structure(object):
  63. assert_size = -1
  64. def __init__(self):
  65. self.data = {}
  66. for field in self.fields:
  67. if len(field) > 2:
  68. f, s, d = field
  69. self.data[s] = d
  70. else:
  71. f, s = field
  72. if f.endswith('s'):
  73. self.data[s] = b""
  74. else:
  75. self.data[s] = 0
  76. if self.assert_size != -1:
  77. assert(len(self) == self.assert_size)
  78. def __len__(self):
  79. return sum([struct.calcsize(f[0]) for f in self.fields])
  80. def read(self, data, offset):
  81. def read_struct(fmt,buf,offset):
  82. out, = struct.unpack_from(fmt,buf,offset)
  83. return out, offset + struct.calcsize(fmt)
  84. o = offset
  85. for field in self.fields:
  86. if len(field) > 2:
  87. f, s, _ = field
  88. else:
  89. f, s = field
  90. self.data[s], o = read_struct(f, data, o)
  91. return o
  92. def write(self, data, offset):
  93. def write_struct(fmt, buf, offset, value):
  94. struct.pack_into(fmt, buf, offset, value)
  95. return offset + struct.calcsize(fmt)
  96. o = offset
  97. for field in self.fields:
  98. if len(field) > 2:
  99. f, s, _ = field
  100. else:
  101. f, s = field
  102. o = write_struct(f,data,o,self.data[s])
  103. return o
  104. def read_struct(fmt,buf,offset):
  105. out, = struct.unpack_from(fmt,buf,offset)
  106. return out, offset + struct.calcsize(fmt)
  107. class FAT(object):
  108. def __init__(self, iso, offset):
  109. self.iso = iso
  110. self.offset = offset
  111. self.bytespersector, _ = read_struct('H', self.iso.data, offset + 11)
  112. self.sectorspercluster, _ = read_struct('B', self.iso.data, offset + 13)
  113. self.reservedsectors, _ = read_struct('H', self.iso.data, offset + 14)
  114. self.numberoffats, _ = read_struct('B', self.iso.data, offset + 16)
  115. self.numberofdirs, _ = read_struct('H', self.iso.data, offset + 17)
  116. self.fatsize, _ = read_struct('H', self.iso.data, offset + 22)
  117. self.root_dir_sectors = (self.numberofdirs * 32 + (self.bytespersector - 1)) // self.bytespersector
  118. self.first_data_sector = self.reservedsectors + (self.numberoffats * self.fatsize) + self.root_dir_sectors
  119. self.root_sector= self.first_data_sector - self.root_dir_sectors
  120. self.root = FATDirectory(self, self.offset + self.root_sector * self.bytespersector)
  121. def get_offset(self, cluster):
  122. return self.offset + ((cluster - 2) * self.sectorspercluster + self.first_data_sector) * self.bytespersector
  123. def get_file(self, path):
  124. units = path.split('/')
  125. units = units[1:]
  126. me = self.root
  127. out = None
  128. for i in units:
  129. for fatfile in me.list():
  130. if fatfile.readable_name() == i:
  131. me = fatfile.to_dir()
  132. out = fatfile
  133. break
  134. else:
  135. return None
  136. return out
  137. class FATDirectory(object):
  138. def __init__(self, fat, offset):
  139. self.fat = fat
  140. self.offset = offset
  141. def list(self):
  142. o = self.offset
  143. while 1:
  144. out = FATFile(self.fat, o)
  145. if out.name != '\0\0\0\0\0\0\0\0':
  146. yield out
  147. else:
  148. break
  149. o += out.size
  150. class FATFile(object):
  151. def __init__(self, fat, offset):
  152. self.fat = fat
  153. self.offset = offset
  154. self.magic_long = None
  155. self.size = 0
  156. self.long_name = ''
  157. o = self.offset
  158. self.actual_offset = o
  159. self.attrib, _ = read_struct('B',self.fat.iso.data,o+11)
  160. while (self.attrib & 0x0F) == 0x0F:
  161. # Long file name entry
  162. tmp = read_struct('10s',self.fat.iso.data,o+1)[0]
  163. tmp += read_struct('12s',self.fat.iso.data,o+14)[0]
  164. tmp += read_struct('4s',self.fat.iso.data,o+28)[0]
  165. tmp = "".join([chr(x) for x in tmp[::2] if x != '\xFF']).strip('\x00')
  166. self.long_name = tmp + self.long_name
  167. self.size += 32
  168. o = self.offset + self.size
  169. self.actual_offset = o
  170. self.attrib, _ = read_struct('B',self.fat.iso.data,o+11)
  171. o = self.offset + self.size
  172. self.name, o = read_struct('8s',self.fat.iso.data,o)
  173. self.ext, o = read_struct('3s',self.fat.iso.data,o)
  174. self.attrib, o = read_struct('B',self.fat.iso.data,o)
  175. self.userattrib, o = read_struct('B',self.fat.iso.data,o)
  176. self.undelete, o = read_struct('b',self.fat.iso.data,o)
  177. self.createtime, o = read_struct('H',self.fat.iso.data,o)
  178. self.createdate, o = read_struct('H',self.fat.iso.data,o)
  179. self.accessdate, o = read_struct('H',self.fat.iso.data,o)
  180. self.clusterhi, o = read_struct('H',self.fat.iso.data,o)
  181. self.modifiedti, o = read_struct('H',self.fat.iso.data,o)
  182. self.modifiedda, o = read_struct('H',self.fat.iso.data,o)
  183. self.clusterlow, o = read_struct('H',self.fat.iso.data,o)
  184. self.filesize, o = read_struct('I',self.fat.iso.data,o)
  185. self.name = self.name.decode('ascii')
  186. self.ext = self.ext.decode('ascii')
  187. self.size += 32
  188. self.cluster = (self.clusterhi << 16) + self.clusterlow
  189. def is_dir(self):
  190. return bool(self.attrib & 0x10)
  191. def is_long(self):
  192. return bool((self.attrib & 0x0F) == 0x0F)
  193. def to_dir(self):
  194. return FATDirectory(self.fat, self.fat.get_offset(self.cluster))
  195. def get_offset(self):
  196. return self.fat.get_offset(self.cluster)
  197. def readable_name(self):
  198. if self.long_name:
  199. return self.long_name
  200. if self.ext.strip():
  201. return (self.name.strip() + '.' + self.ext.strip()).lower()
  202. else:
  203. return self.name.strip().lower()
  204. def make_time():
  205. data = array.array('b',b'\0'*17)
  206. struct.pack_into(
  207. '4s2s2s2s2s2s2sb',
  208. data, 0,
  209. b'2018', b'11', b'14', # Year, Month, Day
  210. b'12', b'00', b'00', # Hour, Minute, Second
  211. b'00', # Hundreths
  212. 0, # Offset
  213. )
  214. return bytes(data)
  215. def make_date():
  216. data = array.array('b',b'\0'*7)
  217. struct.pack_into(
  218. 'BBBBBBb',
  219. data, 0,
  220. 118, 11, 14,
  221. 12, 0, 0,
  222. 0,
  223. )
  224. return bytes(data)
  225. class ISOBootRecord(Structure):
  226. assert_size = 2048
  227. fields = (
  228. ('B', 'type_code', 0),
  229. ('5s', 'cd001', b'CD001'),
  230. ('B', 'version', 1),
  231. ('32s', 'boot_system_identifier'),
  232. ('32s', 'boot_identifier'),
  233. ('1977s', 'boot_record_data'),
  234. )
  235. class ISOElToritoBootRecord(ISOBootRecord):
  236. assert_size = 2048
  237. fields = (
  238. ('B', 'type_code', 0),
  239. ('5s', 'cd001', b'CD001'),
  240. ('B', 'version', 1),
  241. ('32s', 'boot_system_identifier',b'EL TORITO SPECIFICATION'),
  242. ('32s', 'boot_identifier'),
  243. ('<I', 'catalog_lba'),
  244. ('1973s', 'boot_record_data'),
  245. )
  246. def set_catalog(self, catalog_lba):
  247. self.data['catalog_lba'] = catalog_lba
  248. class ISOPrimaryVolumeDescriptor(Structure):
  249. assert_size = 2048
  250. fields = (
  251. ('B', 'type_code', 1),
  252. ('5s', 'cd001', b'CD001'),
  253. ('B', 'version', 1),
  254. ('B', 'unused_0', 0),
  255. ('32s', 'system_id', b' '*32),
  256. ('32s', 'volume_id', b'ToaruOS Boot CD'.ljust(32)),
  257. ('8s', 'unused_1', b'\0'*8),
  258. ('<I', 'volume_space_lsb'),
  259. ('>I', 'volume_space_msb'),
  260. ('32s', 'unused_2', b'\0'*32),
  261. ('<H', 'volume_set_size_lsb', 1),
  262. ('>H', 'volume_set_size_msb', 1),
  263. ('<H', 'volume_sequence_lsb', 1),
  264. ('>H', 'volume_sequence_msb', 1),
  265. ('<H', 'logical_block_size_lsb', 2048),
  266. ('>H', 'logical_block_size_msb', 2048),
  267. ('<I', 'path_table_size_lsb'),
  268. ('>I', 'path_table_size_msb'),
  269. ('<I', 'type_l_table_lsb'),
  270. ('<I', 'optional_type_l_table_lsb'),
  271. ('>I', 'type_m_table_msb'),
  272. ('>I', 'optional_type_m_table_msb'),
  273. ('34s', 'root_entry_data'),
  274. ('128s', 'volume_set_identifier', b' '*128),
  275. ('128s', 'publisher_identifier', b' '*128),
  276. ('128s', 'data_preparer_identifier', b' '*128),
  277. ('128s', 'application_identifier',b' '*128),
  278. ('38s', 'copyright_file_identifier',b' '*38),
  279. ('36s', 'abstract_file_identifier',b' '*36),
  280. ('37s', 'bibliographic_file_identifier',b' '*37),
  281. ('17s', 'volume_creation_time',make_time()),
  282. ('17s', 'volume_modification_time',make_time()),
  283. ('17s', 'volume_expiration_time',make_time()),
  284. ('17s', 'volume_effective_time',make_time()),
  285. ('B', 'file_structure_version'),
  286. ('B', 'unused_3', 0),
  287. ('512s', 'application_data'),
  288. ('653s', 'reserved', b'\0'*653),
  289. )
  290. class ISOVolumeDescriptorSetTerminator(Structure):
  291. assert_size = 2048
  292. fields = (
  293. ('B', 'type_code', 0xFF),
  294. ('5s', 'cd001', b'CD001'),
  295. ('B', 'version', 1),
  296. ('2041s', 'unused', b'\0'*2041)
  297. )
  298. class ISODirectoryEntry(Structure):
  299. assert_size = 33
  300. fields = (
  301. ('B', 'length'),
  302. ('B', 'ext_length'),
  303. ('<I', 'extent_start_lsb'),
  304. ('>I', 'extent_start_msb'),
  305. ('<I', 'extent_length_lsb'),
  306. ('>I', 'extent_length_msb'),
  307. ('7s', 'record_date', make_date()),
  308. ('B', 'flags'),
  309. ('B', 'interleave_units'),
  310. ('B', 'interleave_gap'),
  311. ('<H', 'volume_seq_lsb'),
  312. ('>H', 'volume_seq_msb'),
  313. ('B', 'name_len'),
  314. )
  315. def set_name(self, name):
  316. self.data['name_len'] = len(name)
  317. self.name = name
  318. self.data['length'] = self.assert_size + len(self.name)
  319. if self.data['length'] % 2:
  320. self.data['length'] += 1
  321. def set_extent(self, start, length):
  322. self.data['extent_start_lsb'] = start
  323. self.data['extent_start_msb'] = start
  324. self.data['extent_length_lsb'] = length
  325. self.data['extent_length_msb'] = length
  326. def write(self, data, offset):
  327. o = super(ISODirectoryEntry,self).write(data,offset)
  328. struct.pack_into(str(len(self.name))+'s', data, o, self.name.encode('utf-8'))
  329. return offset + self.data['length']
  330. class ArbitraryData(object):
  331. def __init__(self, path=None, size=None):
  332. if path:
  333. with open(path,'rb') as f:
  334. tmp = f.read()
  335. self.data = array.array('b',tmp)
  336. elif size:
  337. self.data = array.array('b',b'\0'*size)
  338. else:
  339. raise ValueError("Expected one of path or size to be set.")
  340. self.size = len(self.data.tobytes())
  341. self.actual_size = self.size
  342. while (self.size % 2048):
  343. self.size += 1
  344. def write(self, data, offset):
  345. struct.pack_into(str(self.size) + 's', data, offset, self.data.tobytes())
  346. return offset + self.size
  347. def make_entry():
  348. return b'\0'*34
  349. class ISO9660(object):
  350. def __init__(self, from_file=None):
  351. self.primary_volume_descriptor = ISOPrimaryVolumeDescriptor()
  352. self.boot_record = ISOElToritoBootRecord()
  353. self.volume_descriptor_set_terminator = ISOVolumeDescriptorSetTerminator()
  354. self.el_torito_catalog = ElToritoCatalog()
  355. self.allocate = 0x13
  356. if from_file:
  357. # Only for a file we produced.
  358. with open(from_file, 'rb') as f:
  359. tmp = f.read()
  360. data = array.array('b', tmp)
  361. self.primary_volume_descriptor.read(data, 0x10 * 2048)
  362. self.boot_record.read(data, 0x11 * 2048)
  363. self.volume_descriptor_set_terminator.read(data, 0x12 * 2048)
  364. self.el_torito_catalog.read(data, self.boot_record.data['catalog_lba'] * 2048)
  365. else:
  366. # Root directory
  367. self.root = ISODirectoryEntry()
  368. self.root.data['flags'] = 0x02 # Directory
  369. self.root.set_name(' ')
  370. self.root_data = ArbitraryData(size=2048)
  371. self.root_data.sector_offset = self.allocate_space(1)
  372. self.root.set_extent(self.root_data.sector_offset,self.root_data.size)
  373. # Dummy entries
  374. t = ISODirectoryEntry()
  375. t.set_name('')
  376. o = t.write(self.root_data.data, 0)
  377. t = ISODirectoryEntry()
  378. t.set_name('\1')
  379. o = t.write(self.root_data.data, o)
  380. # Kernel
  381. self.kernel_data = ArbitraryData(path='cdrom/kernel')
  382. self.kernel_data.sector_offset = self.allocate_space(self.kernel_data.size // 2048)
  383. self.kernel_entry = ISODirectoryEntry()
  384. self.kernel_entry.set_name('KERNEL.')
  385. self.kernel_entry.set_extent(self.kernel_data.sector_offset, self.kernel_data.actual_size)
  386. o = self.kernel_entry.write(self.root_data.data, o)
  387. # Ramdisk
  388. self.ramdisk_data = ArbitraryData(path='cdrom/ramdisk.img')
  389. self.ramdisk_data.sector_offset = self.allocate_space(self.ramdisk_data.size // 2048)
  390. self.ramdisk_entry = ISODirectoryEntry()
  391. self.ramdisk_entry.set_name('RAMDISK.IMG')
  392. self.ramdisk_entry.set_extent(self.ramdisk_data.sector_offset, self.ramdisk_data.actual_size)
  393. o = self.ramdisk_entry.write(self.root_data.data, o)
  394. # Modules directory
  395. self.mods_data = ArbitraryData(size=(2048*2)) # Just in case
  396. self.mods_data.sector_offset = self.allocate_space(self.mods_data.size // 2048)
  397. self.mods_entry = ISODirectoryEntry()
  398. self.mods_entry.data['flags'] = 0x02
  399. self.mods_entry.set_name('MOD')
  400. self.mods_entry.set_extent(self.mods_data.sector_offset, self.mods_data.actual_size)
  401. o = self.mods_entry.write(self.root_data.data, o)
  402. self.payloads = []
  403. # Modules themselves
  404. t = ISODirectoryEntry()
  405. t.set_name('')
  406. o = t.write(self.mods_data.data, 0)
  407. t = ISODirectoryEntry()
  408. t.set_name('\1')
  409. o = t.write(self.mods_data.data, o)
  410. for mod_file in [
  411. 'cdrom/mod/ac97.ko',
  412. 'cdrom/mod/ata.ko',
  413. 'cdrom/mod/ataold.ko',
  414. 'cdrom/mod/debug_sh.ko',
  415. 'cdrom/mod/dospart.ko',
  416. 'cdrom/mod/e1000.ko',
  417. 'cdrom/mod/ext2.ko',
  418. 'cdrom/mod/hda.ko',
  419. 'cdrom/mod/iso9660.ko',
  420. 'cdrom/mod/lfbvideo.ko',
  421. 'cdrom/mod/net.ko',
  422. 'cdrom/mod/packetfs.ko',
  423. 'cdrom/mod/pcnet.ko',
  424. 'cdrom/mod/pcspkr.ko',
  425. 'cdrom/mod/portio.ko',
  426. 'cdrom/mod/procfs.ko',
  427. 'cdrom/mod/ps2kbd.ko',
  428. 'cdrom/mod/ps2mouse.ko',
  429. 'cdrom/mod/random.ko',
  430. 'cdrom/mod/rtl.ko',
  431. 'cdrom/mod/serial.ko',
  432. 'cdrom/mod/snd.ko',
  433. 'cdrom/mod/tmpfs.ko',
  434. 'cdrom/mod/usbuhci.ko',
  435. 'cdrom/mod/vbox.ko',
  436. 'cdrom/mod/vgadbg.ko',
  437. 'cdrom/mod/vgalog.ko',
  438. 'cdrom/mod/vidset.ko',
  439. 'cdrom/mod/vmware.ko',
  440. 'cdrom/mod/xtest.ko',
  441. 'cdrom/mod/zero.ko',
  442. 'cdrom/mod/tarfs.ko',
  443. ]:
  444. payload = ArbitraryData(path=mod_file)
  445. payload.sector_offset = self.allocate_space(payload.size // 2048)
  446. entry = ISODirectoryEntry()
  447. entry.set_name(mod_file.replace('cdrom/mod/','').upper())
  448. entry.set_extent(payload.sector_offset, payload.actual_size)
  449. o = entry.write(self.mods_data.data, o)
  450. self.payloads.append(payload)
  451. # Set up the boot catalog and records
  452. self.el_torito_catalog.sector_offset = self.allocate_space(1)
  453. self.boot_record.set_catalog(self.el_torito_catalog.sector_offset)
  454. subprocess.run("cp /cdrom/boot.sys /tmp/boot.sys")
  455. self.boot_payload = ArbitraryData(path='/tmp/boot.sys')
  456. self.boot_payload.sector_offset = self.allocate_space(self.boot_payload.size // 2048)
  457. self.el_torito_catalog.initial_entry.data['sector_count'] = self.boot_payload.size // 512
  458. self.el_torito_catalog.initial_entry.data['load_rba'] = self.boot_payload.sector_offset
  459. #self.el_torito_catalog.section.data['sector_count'] = 0 # Expected to be 0 or 1 for "until end of CD"
  460. #self.el_torito_catalog.section.data['load_rba'] = self.fat_payload.sector_offset
  461. self.primary_volume_descriptor.data['root_entry_data'] = make_entry()
  462. def allocate_space(self, sectors):
  463. out = self.allocate
  464. self.allocate += sectors
  465. return out
  466. def write(self, file_name):
  467. with open(file_name, 'wb') as f:
  468. data = array.array('b',b'\0'*(2048*self.allocate))
  469. self.primary_volume_descriptor.write(data,0x10 * 2048)
  470. self.root.write(data,0x10*2048 + 156)
  471. self.boot_record.write(data,0x11 * 2048)
  472. self.mods_data.write(data, self.mods_data.sector_offset * 2048)
  473. self.root_data.write(data,self.root_data.sector_offset * 2048)
  474. self.volume_descriptor_set_terminator.write(data,0x12 * 2048)
  475. self.el_torito_catalog.write(data,self.el_torito_catalog.sector_offset * 2048)
  476. self.boot_payload.write(data,self.boot_payload.sector_offset * 2048)
  477. self.kernel_data.write(data,self.kernel_data.sector_offset * 2048)
  478. self.ramdisk_data.write(data,self.ramdisk_data.sector_offset * 2048)
  479. #self.fat_payload.write(data,self.fat_payload.sector_offset * 2048)
  480. for payload in self.payloads:
  481. payload.write(data,payload.sector_offset * 2048)
  482. data.tofile(f)
  483. class ElToritoValidationEntry(Structure):
  484. assert_size = 0x20
  485. fields = (
  486. ('B','header_id',1),
  487. ('B','platform_id',0),
  488. ('<H','reserved_0'),
  489. ('24s','id_str',b'\0'*24),
  490. ('<H','checksum',0x55aa),
  491. ('B','key_55',0x55),
  492. ('B','key_aa',0xaa),
  493. )
  494. class ElToritoInitialEntry(Structure):
  495. assert_size = 0x20
  496. fields = (
  497. ('B','bootable',0x88),
  498. ('B','media_type'),
  499. ('<H','load_segment'),
  500. ('B','system_type'),
  501. ('B','unused_0'),
  502. ('<H','sector_count'),
  503. ('<I','load_rba'),
  504. ('20s','unused_1',b'\0'*20),
  505. )
  506. class ElToritoSectionHeader(Structure):
  507. assert_size = 0x20
  508. fields = (
  509. ('B','header_id',0x91),
  510. ('B','platform_id',0xEF),
  511. ('<H','sections',1),
  512. ('28s','id_str',b'\0'*28)
  513. )
  514. class ElToritoSectionEntry(Structure):
  515. assert_size = 0x20
  516. fields = (
  517. ('B','bootable',0x88),
  518. ('B','media_type'),
  519. ('<H','load_segment'),
  520. ('B','system_type'),
  521. ('B','unused_0'),
  522. ('<H','sector_count'),
  523. ('<I','load_rba'),
  524. ('B','selection_criteria'),
  525. ('19s','vendor'),
  526. )
  527. class ElToritoCatalog(object):
  528. def __init__(self):
  529. self.validation_entry = ElToritoValidationEntry()
  530. self.initial_entry = ElToritoInitialEntry()
  531. self.section_header = ElToritoSectionHeader()
  532. self.section = ElToritoSectionEntry()
  533. def read(self, data, offset):
  534. o = offset
  535. o = self.validation_entry.read(data, o)
  536. o = self.initial_entry.read(data, o)
  537. o = self.section_header.read(data, o)
  538. o = self.section.read(data, o)
  539. def write(self, data, offset):
  540. o = offset
  541. o = self.validation_entry.write(data, o)
  542. o = self.initial_entry.write(data, o)
  543. o = self.section_header.write(data, o)
  544. o = self.section.write(data, o)
  545. def BuildISO():
  546. iso = ISO9660()
  547. iso.write('toaruos.iso')
  548. def BuildRamdisk():
  549. users = {
  550. 'root': 0,
  551. 'local': 1000,
  552. }
  553. restricted_files = {
  554. 'etc/master.passwd': 0o600,
  555. 'etc/sudoers': 0o600,
  556. 'tmp': 0o777,
  557. 'var': 0o755,
  558. 'bin/sudo': 0o4555,
  559. 'bin/gsudo': 0o4555,
  560. }
  561. def file_filter(tarinfo):
  562. # Root owns files by default.
  563. tarinfo.uid = 0
  564. tarinfo.gid = 0
  565. if tarinfo.name.startswith('home/'):
  566. # Home directory contents are owned by their users.
  567. user = tarinfo.name.split('/')[1]
  568. tarinfo.uid = users.get(user,0)
  569. tarinfo.gid = tarinfo.uid
  570. elif tarinfo.name in restricted_files:
  571. tarinfo.mode = restricted_files[tarinfo.name]
  572. if tarinfo.name.startswith('src'):
  573. # Let local own the files here
  574. tarinfo.uid = users.get('local')
  575. tarinfo.gid = tarinfo.uid
  576. # Skip object files
  577. if tarinfo.name.endswith('.so') or tarinfo.name.endswith('.o'):
  578. return None
  579. return tarinfo
  580. with tarfile.open('cdrom/ramdisk.img','w') as ramdisk:
  581. ramdisk.add('/',arcname='/',filter=file_filter,recursive=False) # Add a blank directory
  582. ramdisk.add('/bin',arcname='/bin',filter=file_filter)
  583. ramdisk.add('/',arcname='/usr',filter=file_filter,recursive=False) # Add a blank directory
  584. ramdisk.add('/usr/share',arcname='/usr/share',filter=file_filter)
  585. ramdisk.add('/',arcname='/usr/bin',filter=file_filter,recursive=False) # Add a blank directory
  586. ramdisk.add('/',arcname='/usr/lib',filter=file_filter,recursive=False) # Add a blank directory
  587. ramdisk.add('/usr/include',arcname='/usr/include',filter=file_filter)
  588. ramdisk.add('/',arcname='/dev',filter=file_filter,recursive=False) # Add a blank directory
  589. ramdisk.add('/',arcname='/cdrom',filter=file_filter,recursive=False) # Add a blank directory
  590. ramdisk.add('/etc',arcname='/etc',filter=file_filter)
  591. ramdisk.add('/',arcname='/var',filter=file_filter,recursive=False) # Add a blank directory
  592. ramdisk.add('/',arcname='/tmp',filter=file_filter,recursive=False) # Add a blank directory
  593. ramdisk.add('/',arcname='/proc',filter=file_filter,recursive=False) # Add a blank directory
  594. ramdisk.add('/home',arcname='/home',filter=file_filter)
  595. ramdisk.add('/lib',arcname='/lib',filter=file_filter)
  596. ramdisk.add('/opt',arcname='/opt',filter=file_filter)
  597. ramdisk.add('.',arcname='/src',filter=file_filter,recursive=False) # Add a blank directory
  598. ramdisk.add('apps',arcname='/src/apps',filter=file_filter)
  599. ramdisk.add('kernel',arcname='/src/kernel',filter=file_filter)
  600. ramdisk.add('linker',arcname='/src/linker',filter=file_filter)
  601. ramdisk.add('lib',arcname='/src/lib',filter=file_filter)
  602. ramdisk.add('libc',arcname='/src/libc',filter=file_filter)
  603. ramdisk.add('boot',arcname='/src/boot',filter=file_filter)
  604. ramdisk.add('modules',arcname='/src/boot',filter=file_filter)
  605. ramdisk.add('/usr/bin/build-the-world.py',arcname='/usr/bin/build-the-world.py',filter=file_filter)
  606. if __name__ == '__main__':
  607. try:
  608. os.mkdir('cdrom')
  609. except:
  610. pass
  611. print("Building the kernel...")
  612. BuildKernel()
  613. print("Building modules...")
  614. BuildModules()
  615. print("Createing ramdisk...")
  616. BuildRamdisk()
  617. print("Building ISO...")
  618. BuildISO()