Browse Source

make: Replace update-extents.py with a Kuroko equivalent

K. Lange 11 months ago
parent
commit
1cb7195d75
4 changed files with 151 additions and 56 deletions
  1. 6 2
      Makefile
  2. 1 1
      kuroko
  3. 0 1
      util/build-toolchain.sh
  4. 144 52
      util/update-extents.py

+ 6 - 2
Makefile

@@ -305,10 +305,14 @@ fatbase/efi/boot/bootx64.efi: boot/efi64.so
 	mkdir -p fatbase/efi/boot
 	objcopy ${EFI_SECTIONS} --target=efi-app-x86_64 $< $@
 
-image.iso: cdrom/fat.img cdrom/boot.sys util/update-extents.py
+BUILD_KRK=$(TOOLCHAIN)/local/bin/kuroko
+$(TOOLCHAIN)/local/bin/kuroko: kuroko/src/*.c
+	cc -Ikuroko/src -DNO_RLINE -DSTATIC_ONLY -DKRK_DISABLE_THREADS -o "${TOOLCHAIN}/local/bin/kuroko" kuroko/src/*.c
+
+image.iso: cdrom/fat.img cdrom/boot.sys util/update-extents.krk $(BUILD_KRK)
 	xorriso -as mkisofs -R -J -c bootcat \
 	  -b boot.sys -no-emul-boot -boot-load-size full \
 	  -eltorito-alt-boot -e fat.img -no-emul-boot -isohybrid-gpt-basdat \
 	  -o image.iso cdrom
-	python3 util/update-extents.py
+	kuroko util/update-extents.krk
 

+ 1 - 1
kuroko

@@ -1 +1 @@
-Subproject commit caf3c1a227f9a5e502d6e0ec6ed92b38da0d2a0e
+Subproject commit b4887a78b0e8f5d2883c73c0935548d086a7ca9c

+ 0 - 1
util/build-toolchain.sh

@@ -5,7 +5,6 @@ SYSROOT="$DIR/../base"
 
 cd $DIR
 mkdir -p $PREFIX/bin
-gcc -I$DIR/../kuroko/src -DNO_RLINE -DSTATIC_ONLY -DKRK_DISABLE_THREADS -o "$PREFIX/bin/kuroko" $DIR/../kuroko/src/*.c
 
 mkdir -p $DIR/build/binutils
 cd $DIR/build/binutils

+ 144 - 52
util/update-extents.py

@@ -1,29 +1,118 @@
-#!/usr/bin/env python3
-import array
-import struct
-
-def read_struct(fmt,buf,offset):
-    out, = struct.unpack_from(fmt,buf,offset)
-    return out, offset + struct.calcsize(fmt)
+#!/usr/bin/env kuroko
+import fileio
+
+def to_int(little: bool, data: bytes):
+    let out = 0
+    if little: data = reversed(data)
+    for x in data:
+        out *= 0x100
+        out += x
+    return out
+
+def to_bytes(little: bool, val: int, length: int):
+    let out = [0] * length
+    let i = 0
+    while val and i < length:
+        out[i] = val & 0xFF
+        val >>= 8
+        i++
+    if not little:
+        out = reversed(out)
+    return bytes(out)
+
+def read_struct(fmt: str, data: bytes, offset: int):
+    if not fmt or not isinstance(fmt,str):
+        raise ValueError
+    # First, read the endianness
+    let littleEndian = True
+    if fmt[0] in '@<>#!':
+        if fmt[0] == '>': littleEndian = False
+        else if fmt[0] == '!': littleEndian = False
+        fmt = fmt[1:]
+    # Then read length
+    let length = None
+    if fmt[0] in '0123456789':
+        length = int(fmt[0])
+        fmt = fmt[1:]
+        while fmt[0] in '012345679':
+            length *= 10
+            length += int(fmt[0])
+            fmt = fmt[1:]
+    # Then read type
+    if fmt[0] == 'B':
+        return int(data[offset]), offset + 1
+    else if fmt[0] == 'b':
+        let out = int(data[offset])
+        if out > 0x7F: out = -out
+        return out, offset + 1
+    else if fmt[0] == 's':
+        return bytes([data[x] for x in range(offset,offset+length)]), offset + length
+    else if fmt[0] == 'I':
+        return to_int(littleEndian, bytes([data[x] for x in range(offset,offset+4)])), offset + 4
+    else if fmt[0] == 'H':
+        return to_int(littleEndian, bytes([data[x] for x in range(offset,offset+2)])), offset + 2
+    raise ValueError("Huh")
+
+def pack_into(fmt: str, data: bytes, offset: int, val: any):
+    if not fmt or not isinstance(fmt,str):
+        raise ValueError
+    # First, read the endianness
+    let littleEndian = True
+    if fmt[0] in '@<>#!':
+        if fmt[0] == '>': littleEndian = False
+        else if fmt[0] == '!': littleEndian = False
+        fmt = fmt[1:]
+    # Then read length
+    let length = None
+    if fmt[0] in '0123456789':
+        length = int(fmt[0])
+        fmt = fmt[1:]
+        while fmt[0] in '012345679':
+            length *= 10
+            length += int(fmt[0])
+            fmt = fmt[1:]
+    # Then read type
+    if fmt[0] == 'B':
+        data[offset] = val
+        return offset + 1
+    else if fmt[0] == 'b':
+        data[offset] = val
+        return offset + 1
+    else if fmt[0] == 's':
+        for x in range(length):
+            data[offset+x] = val[x]
+        return offset + length
+    else if fmt[0] == 'I':
+        for x in to_bytes(littleEndian, val, 4):
+            data[offset] = x
+            offset++
+        return offset
+    else if fmt[0] == 'H':
+        for x in to_bytes(littleEndian, val, 2):
+            data[offset] = x
+            offset++
+        return offset
+    raise ValueError("Huh")
 
 class ISO(object):
 
     def __init__(self, path):
-        with open(path, 'rb') as f:
-            tmp = f.read()
-            self.data = array.array('b', tmp)
+        let data
+        with fileio.open(path, 'rb') as f:
+            self.data = bytearray(f.read())
         self.sector_size = 2048
-        o = 0x10 * self.sector_size
+        let o = 0x10 * self.sector_size
+        let _unused
         self.type,             o = read_struct('B',self.data,o)
         self.id,               o = read_struct('5s',self.data,o)
         self.version,          o = read_struct('B',self.data,o)
-        _unused0,              o = read_struct('B',self.data,o)
+        _unused,               o = read_struct('B',self.data,o)
         self.system_id,        o = read_struct('32s',self.data,o)
         self.volume_id,        o = read_struct('32s',self.data,o)
-        _unused1,              o = read_struct('8s',self.data,o)
+        _unused,               o = read_struct('8s',self.data,o)
         self.volume_space_lsb, o = read_struct('<I',self.data,o)
         self.volume_space_msb, o = read_struct('>I',self.data,o)
-        _unused2,              o = read_struct('32s',self.data,o)
+        _unused,               o = read_struct('32s',self.data,o)
         self.volume_set_lsb,   o = read_struct('<H',self.data,o)
         self.volume_set_msb,   o = read_struct('>H',self.data,o)
         self.volume_seq_lsb,   o = read_struct('<H',self.data,o)
@@ -36,7 +125,7 @@ class ISO(object):
         self.optional_path_table_lsb,   o = read_struct('<I',self.data,o)
         self.path_table_msb,   o = read_struct('>I',self.data,o)
         self.optional_path_table_msb,   o = read_struct('>I',self.data,o)
-        _offset = o
+        let _offset = o
         self.root_dir_entry, o = read_struct('34s',self.data,o)
 
         self.root = ISOFile(self,_offset)
@@ -48,11 +137,11 @@ class ISO(object):
         else:
             if path in self._cache:
                 return self._cache[path]
-            units = path.split('/')
+            let units = path.split('/')
             units = units[1:] # remove root
-            me = self.root
+            let me = self.root
             for i in units:
-                next_file = me.find(i)
+                let next_file = me.find(i)
                 if not next_file:
                     me = None
                     break
@@ -67,7 +156,7 @@ class ISOFile(object):
         self.iso = iso
         self.offset = offset
 
-        o = offset
+        let o = offset
         self.length,            o = read_struct('B', self.iso.data, o)
         if not self.length:
             return
@@ -88,43 +177,45 @@ class ISOFile(object):
 
         self.name_len, o = read_struct('b', self.iso.data, o)
         self.name, o = read_struct('{}s'.format(self.name_len), self.iso.data, o)
-        self.name = self.name.decode('ascii')
+        self.name = self.name.decode()
 
     def write_extents(self):
-        struct.pack_into('<I', self.iso.data, self.offset + 2, self.extent_start_lsb)
-        struct.pack_into('>I', self.iso.data, self.offset + 6, self.extent_start_lsb)
-        struct.pack_into('<I', self.iso.data, self.offset + 10, self.extent_length_lsb)
-        struct.pack_into('>I', self.iso.data, self.offset + 14, self.extent_length_lsb)
+        pack_into('<I', self.iso.data, self.offset + 2, self.extent_start_lsb)
+        pack_into('>I', self.iso.data, self.offset + 6, self.extent_start_lsb)
+        pack_into('<I', self.iso.data, self.offset + 10, self.extent_length_lsb)
+        pack_into('>I', self.iso.data, self.offset + 14, self.extent_length_lsb)
 
     def readable_name(self):
         if not ';' in self.name:
             return self.name.lower()
         else:
+            let tmp, _
             tmp, _ = self.name.split(';')
             return tmp.lower()
 
 
     def list(self):
-        sectors = self.iso.data[self.extent_start_lsb * self.iso.sector_size: self.extent_start_lsb * self.iso.sector_size+ 3 * self.iso.sector_size]
-        offset = 0
+        let sectors = self.iso.data[self.extent_start_lsb * self.iso.sector_size: self.extent_start_lsb * self.iso.sector_size+ 3 * self.iso.sector_size]
+        let offset = 0
 
         while 1:
-            f = ISOFile(self.iso, self.extent_start_lsb * self.iso.sector_size + offset)
+            let f = ISOFile(self.iso, self.extent_start_lsb * self.iso.sector_size + offset)
             yield f
             offset += f.length
             if not f.length:
                 break
 
     def find(self, name):
-        sectors = self.iso.data[self.extent_start_lsb * self.iso.sector_size: self.extent_start_lsb * self.iso.sector_size+ 3 * self.iso.sector_size]
-        offset = 0
+        let sectors = self.iso.data[self.extent_start_lsb * self.iso.sector_size: self.extent_start_lsb * self.iso.sector_size+ 3 * self.iso.sector_size]
+        let offset = 0
         if '.' in name and len(name.split('.')[0]) > 8:
+            let a, b
             a, b = name.split('.')
             name = a[:8] + '.' + b
         if '-' in name:
             name = name.replace('-','_')
         while 1:
-            f = ISOFile(self.iso, self.extent_start_lsb * self.iso.sector_size + offset)
+            let f = ISOFile(self.iso, self.extent_start_lsb * self.iso.sector_size + offset)
             if not f.length:
                 if offset < self.extent_length_lsb:
                     offset += 1
@@ -132,6 +223,7 @@ class ISOFile(object):
                 else:
                     break
             if ';' in f.name:
+                let tmp, _
                 tmp, _ = f.name.split(';')
                 if tmp.endswith('.'):
                     tmp = tmp[:-1]
@@ -148,6 +240,7 @@ class FAT(object):
         self.iso = iso
         self.offset = offset
 
+        let _
         self.bytespersector,    _ = read_struct('H', self.iso.data, offset + 11)
         self.sectorspercluster, _ = read_struct('B', self.iso.data, offset + 13)
         self.reservedsectors,   _ = read_struct('H', self.iso.data, offset + 14)
@@ -164,33 +257,29 @@ class FAT(object):
         return self.offset + ((cluster - 2) * self.sectorspercluster + self.first_data_sector) * self.bytespersector
 
     def get_file(self, path):
-        units = path.split('/')
+        let units = path.split('/')
         units = units[1:]
 
-        me = self.root
-        out = None
+        let me = self.root
+        let out = None
         for i in units:
             for fatfile in me.list():
                 if fatfile.readable_name() == i:
                     me = fatfile.to_dir()
                     out = fatfile
                     break
-            else:
-                return None
         return out
 
 class FATDirectory(object):
 
     def __init__(self, fat, offset):
-
         self.fat = fat
         self.offset = offset
 
     def list(self):
-
-        o = self.offset
+        let o = self.offset
         while 1:
-            out = FATFile(self.fat, o)
+            let out = FATFile(self.fat, o)
             if out.name != '\0\0\0\0\0\0\0\0':
                 yield out
             else:
@@ -208,17 +297,22 @@ class FATFile(object):
         self.size = 0
         self.long_name = ''
 
-        o = self.offset
+        let o = self.offset
         self.actual_offset = o
 
+        let _
         self.attrib,     _ = read_struct('B',self.fat.iso.data,o+11)
 
         while (self.attrib & 0x0F) == 0x0F:
             # Long file name entry
-            tmp = read_struct('10s',self.fat.iso.data,o+1)[0]
+            let tmp = read_struct('10s',self.fat.iso.data,o+1)[0]
             tmp += read_struct('12s',self.fat.iso.data,o+14)[0]
             tmp += read_struct('4s',self.fat.iso.data,o+28)[0]
-            tmp = "".join([chr(x) for x in tmp[::2] if x != '\xFF']).strip('\x00')
+            let s = []
+            for i = 0; i < len(tmp); i += 2:
+                if tmp[x] != '\xFF':
+                    s.append(chr(tmp[x]))
+            tmp = "".join(s).strip('\x00')
             self.long_name = tmp + self.long_name
             self.size += 32
             o = self.offset + self.size
@@ -241,8 +335,8 @@ class FATFile(object):
         self.clusterlow, o = read_struct('H',self.fat.iso.data,o)
         self.filesize,   o = read_struct('I',self.fat.iso.data,o)
 
-        self.name = self.name.decode('ascii')
-        self.ext  = self.ext.decode('ascii')
+        self.name = self.name.decode()
+        self.ext  = self.ext.decode()
 
         self.size += 32
 
@@ -268,11 +362,9 @@ class FATFile(object):
         else:
             return self.name.strip().lower()
 
-
-image = ISO('image.iso')
-fat = image.root.find('FAT.IMG')
-
-fatfs = FAT(image, fat.extent_start_lsb * image.sector_size)
+let image = ISO('image.iso')
+let fat = image.root.find('FAT.IMG')
+let fatfs = FAT(image, fat.extent_start_lsb * image.sector_size)
 
 def process(fatfile, path):
     if fatfile.is_long():
@@ -285,7 +377,7 @@ def process(fatfile, path):
         for i in fatfile.to_dir().list():
             process(i, path + fatfile.readable_name() + '/')
     else:
-        cdfile = image.get_file(path + fatfile.readable_name())
+        let cdfile = image.get_file(path + fatfile.readable_name())
         if not cdfile:
             if fatfile.readable_name() != 'bootia32.efi' and fatfile.readable_name() != 'bootx64.efi':
                 print("Warning:", fatfile.readable_name(), "not found in ISO")
@@ -298,6 +390,6 @@ def process(fatfile, path):
 for i in fatfs.root.list():
     process(i,'/')
 
-with open('image.iso','wb') as f:
-    f.write(image.data)
+with fileio.open('image.iso','wb') as f:
+    f.write(bytes(image.data))