WIP: RPi3 RPi4
authorŁukasz Stelmach <l.stelmach@samsung.com>
Tue, 19 Sep 2023 15:27:28 +0000 (17:27 +0200)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Wed, 20 Sep 2023 12:15:01 +0000 (14:15 +0200)
Change-Id: I88d9cc80e3cecfd694acbb6595cde66e2eb3771d
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
scripts/tizen/sd_fusing.py

index 04d67ae..3323e93 100755 (executable)
@@ -4,6 +4,7 @@ from functools import reduce
 
 import argparse
 import atexit
+import errno
 import logging
 import os
 import re
@@ -19,44 +20,145 @@ Device = ""
 File = ""
 
 class Partition:
-    def __init__(self, name, size, start=None, ptype="0FC63DAF-8483-4772-8E79-3D69D8477DE4", fstype="raw"):
+    def __init__(self, name, size, start=None, ptype=None, fstype="raw", bootable=False):
         self.name = name
         self.size = size
         self.start = start
         self.ptype = ptype
+        self.bootable = bootable
     def __str__(self):
-        output = f"start={self.start}MiB, " if self.start else ""
-        output += f"size={self.size}MiB"
-        output += f", name={self.name}"
-        output += f", type={self.ptype}"
-        return output + "\n"
+        output = []
+        if self.start:
+            output.append(f"start={self.start}MiB")
+        if self.size:
+            output.append(f"size={self.size}MiB")
+        if self.name:
+            output.append(f"name={self.name}")
+        output.append(f"type={self.ptype}")
+        if self.bootable:
+                       output.append("bootable")
+        return ", ".join(output) + "\n"
 
 class Label:
     def __init__(self, part_table, ltype):
         self.ltype = ltype
+        if ltype == 'gpt':
+            ptype = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
+        elif ltype == 'dos':
+            ptype = '83'
         self.part_table = []
         for part in part_table:
-            name = part["name"]
-            size = part["size"]
-            ptype = part.get("type", None)
-            ftype = part["fstype"]
-            start = part.get("start", None)
-            self.part_table.append(Partition(**part)) #name, size, start, ptype, ftype))
+            part["ptype"] = part.get("ptype", ptype)
+            self.part_table.append(Partition(**part))
     def __str__(self):
         output = f"label: {self.ltype}\n"
         for part in self.part_table:
             output += str(part)
         return output
 
-class Rpi3:
+class SdFusingTarget:
+    def __init__(self, device, ltype):
+        self.device = device
+        total_size = device_size(device)
+        self.user_size = total_size - self.reserved_space - \
+            reduce(lambda x, y: x + (y["size"] or 0), self.part_table, 0)
+        if self.user_size < 100:
+            logging.error("Not enough space for user data. Use larger storage.")
+            raise OSError(errno.ENOSPC, os.strerror(errno.ENOSPC), device)
+        self.part_table[self.user_partition]["size"] = self.user_size
+        self.label = Label(self.part_table, ltype)
+
+    def get_partition_index(self, binary):
+        return self.binaries.get(binary, None)
+
+class Rpi3(SdFusingTarget):
     long_name = "Raspberry Pi 3"
-    pass
+    part_table = [
+        {"size": 64,   "fstype": "vfat", "name": "boot", "start": 4, "ptype": "0xe", "bootable": True},
+        {"size": 3072, "fstype": "ext4", "name": "rootfs"},
+        {"size": 1344, "fstype": "ext4", "name": "system-data"},
+        {"size": None, "ptype":  "5",    "name": "extended", "start": 4484},
+        {"size": None, "fstype": "ext4", "name": "user"},
+        {"size": 32,   "fstype": "ext4", "name": "modules"},
+        {"size": 32,   "fstype": "ext4", "name": "ramdisk"},
+        {"size": 32,   "fstype": "ext4", "name": "ramdisk-recovery"},
+        {"size": 8,    "fstype": "raw",  "name": "inform"},
+        {"size": 256,  "fstype": "ext4", "name": "hal"},
+        {"size": 125,  "fstype": "raw",  "name": "reserved2"},
+    ]
+    binaries = {
+        "boot.img":             1,
+        "rootfs.img":           2,
+        "system-data.img":      3,
+        "user.img":             5,
+        "modules.img":          6,
+        "ramdisk.img":          7,
+        "ramdisk-recovery.img": 8,
+        "hal.img":              10,
+    }
 
-class Rpi4:
+    def __init__(self, device, args):
+        self.reserved_space = 12
+        self.user_partition = 4
+        super().__init__(device, "dos")
+
+class Rpi4(SdFusingTarget):
     long_name = "Raspberry Pi 4"
-    pass
+    part_table = [
+       {"size": 64,   "fstype": "vfat", "name": "boot_a", "start": 4,
+         "ptype": "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"},
+       {"size": 3072, "fstype": "ext4", "name": "rootfs_a"},
+       {"size": 1344, "fstype": "ext4", "name": "system-data"},
+        {"size": 36,   "fstype": "raw",  "name": "none"},
+       {"size": None, "fstype": "ext4", "name": "user"},
+       {"size": 32,   "fstype": "ext4", "name": "module_a"},
+       {"size": 32,   "fstype": "ext4", "name": "ramdisk_a"},
+       {"size": 32,   "fstype": "ext4", "name": "ramdisk-recovery_a"},
+       {"size": 8,    "fstype": "ext4", "name": "inform"},
+       {"size": 256,  "fstype": "ext4", "name": "hal_a"},
+       {"size": 64,   "fstype": "vfat", "name": "boot_b",
+         "ptype": "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"},
+       {"size": 3072, "fstype": "ext4", "name": "rootfs_b"},
+       {"size": 32,   "fstype": "ext4", "name": "module_b"},
+       {"size": 32,   "fstype": "ext4", "name": "ramdisk_b"},
+       {"size": 32,   "fstype": "ext4", "name": "ramdisk-recovery_b"},
+       {"size": 256,  "fstype": "ext4", "name": "hal_b"},
+       {"size": 4,    "fstype": "ext4", "name": "param"},
+       {"size": 64,  "fstype": "ext4", "name": "reserved1"},
+       {"size": 125,  "fstype": "ext4", "name": "reserved2"},
+    ]
+    binaries = {
+       "boot.img":              1,
+       "rootfs.img":            2,
+       "system-data.img":       3,
+       "user.img":              5,
+       "modules.img":           6,
+       "ramdisk.img":           7,
+       "ramdisk-recovery.img":  8,
+       "hal.img":              10,
+    }
+    binaries_b = {
+       "boot.img":             11,
+       "rootfs.img":           12,
+       "modules.img":          13,
+       "ramdisk.img":          14,
+       "ramdisk-recovery.img": 15,
+       "hal.img":              16,
+    }
 
-class RV64:
+    def __init__(self, device, args):
+        self.reserved_space = 5
+        self.user_partition = 4
+        self.update = args.update
+        super().__init__(device, "gpt")
+
+    def get_partition_index(self, binary):
+        logging.debug(f"RPi4 get_partition_index: {binary} {repr(self.update)}")
+        if self.update == 'b':
+            self.binaries_b.get(binary, None)
+        return self.binaries.get(binary, None)
+
+class RV64(SdFusingTarget):
     long_name = "QEMU RISC-V 64-bit"
     part_table = [
         {"size": 2,    "fstype": "raw",  "name": "SPL", "start": 4,
@@ -91,15 +193,11 @@ class RV64:
         "ramdisk-recovery.img":          10,
         "hal.img":                       12,
     }
-    def __init__(self, device):
-        self.device = device
-        total_size = device_size(device)
-        user_size = total_size - reduce(lambda x, y: x + (y["size"] or 0), self.part_table, 0)
-        self.part_table[6]["size"] = user_size
-        self.label = Label(self.part_table, "gpt")
 
-    def get_partition_index(self, binary):
-        return self.binaries.get(binary, None)
+    def __init__(self, device, args):
+        self.user_partition = 6
+        self.reserved_space = 5
+        super().__init__(device, 'gpt')
 
 class VF2:
     long_name = "VisionFive2"
@@ -142,7 +240,7 @@ def mkpart(args):
 
     if not new:
          sys.exit(1)
-    target = TARGETS[args.target](Device)
+    target = TARGETS[args.target](Device, args)
 
     #TODO: unmount target devices
     if support_delete:
@@ -295,7 +393,7 @@ def fuse_image(args):
     if args.binaries is None or len(args.binaries) == 0:
         return
 
-    target = TARGETS[args.target](Device)
+    target = TARGETS[args.target](Device, args)
     for b in args.binaries:
         if re.search('\.(tar|tar\.gz|tgz)$', b):
             do_fuse_image_tarball(b, target)
@@ -318,11 +416,13 @@ if __name__ == '__main__':
     parser.add_argument("--log-level", dest="log_level", default="warning",
                         help="Verbosity, possible values: debug, info, warning, "
                         "error, critical (default: warning)")
-    parser.add_argument("-s", "--size", type=int, default=8192,
-                        help="size of the backing file to create")
+    parser.add_argument("--size", type=int, default=8192,
+                        help="size of the backing file to create (in MiB)")
     parser.add_argument("-t", "--target", required=True,
                         help="Target device model. Use `--target list`"
                         " to show supported devices.")
+    parser.add_argument("--update", choices=['a', 'b'], default=None,
+                        help="Choose partition set to update: A or B.")
     parser.add_argument("--version", action="version",
                         version=f"%(prog)s {__version__}")
     args = parser.parse_args()