luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

partition.c (9487B)


      1 /* Partition Table Handler for LuajitOS
      2  *
      3  * Implements MBR partition table reading/writing
      4  */
      5 
      6 #include "partition.h"
      7 #include "ata.h"
      8 #include <string.h>
      9 #include <stdio.h>
     10 
     11 /* External terminal function for debug output */
     12 extern void terminal_writestring(const char *str);
     13 
     14 /* ============================================================================
     15  * Internal Helpers
     16  * ========================================================================= */
     17 
     18 /* Convert CHS to LBA (not really needed, we use LBA directly) */
     19 static uint32_t chs_to_lba(uint8_t head, uint8_t sector, uint8_t cyl) {
     20     /* Assuming 255 heads, 63 sectors per track */
     21     return (cyl * 255 + head) * 63 + (sector - 1);
     22 }
     23 
     24 /* Convert LBA to CHS (for compatibility) */
     25 static void lba_to_chs(uint32_t lba, uint8_t *head, uint8_t *sector, uint8_t *cyl) {
     26     /* Use dummy CHS for LBA-only access (works for drives > 8GB) */
     27     if (lba >= 16450560) {  /* Max CHS addressable */
     28         *head = 254;
     29         *sector = 63;
     30         *cyl = 255;  /* Max value for uint8_t (actual CHS max is 1023 but stored differently) */
     31     } else {
     32         *cyl = (uint8_t)(lba / (255 * 63));
     33         uint32_t temp = lba % (255 * 63);
     34         *head = (uint8_t)(temp / 63);
     35         *sector = (uint8_t)((temp % 63) + 1);
     36     }
     37 }
     38 
     39 /* ============================================================================
     40  * Public API
     41  * ========================================================================= */
     42 
     43 int partition_read_table(uint8_t bus, uint8_t drive, partition_info_t parts[4]) {
     44     mbr_t mbr;
     45 
     46     if (ata_read_sectors(bus, drive, 0, 1, &mbr) != ATA_OK) {
     47         return -1;
     48     }
     49 
     50     /* Check MBR signature */
     51     if (mbr.signature != MBR_SIGNATURE) {
     52         /* No valid MBR, return empty partitions */
     53         memset(parts, 0, sizeof(partition_info_t) * 4);
     54         return 0;
     55     }
     56 
     57     for (int i = 0; i < 4; i++) {
     58         partition_entry_t *pe = &mbr.partitions[i];
     59         partition_info_t *pi = &parts[i];
     60 
     61         if (pe->type == PART_TYPE_EMPTY) {
     62             memset(pi, 0, sizeof(partition_info_t));
     63         } else {
     64             pi->exists = 1;
     65             pi->bootable = (pe->bootable == 0x80);
     66             pi->type = pe->type;
     67             pi->start_lba = pe->lba_start;
     68             pi->sector_count = pe->sector_count;
     69             pi->size_mb = (uint32_t)((uint64_t)pe->sector_count * 512 / (1024 * 1024));
     70         }
     71     }
     72 
     73     return 0;
     74 }
     75 
     76 int partition_write_table(uint8_t bus, uint8_t drive, const partition_entry_t parts[4]) {
     77     mbr_t mbr;
     78 
     79     /* Initialize MBR with zeros */
     80     memset(&mbr, 0, sizeof(mbr));
     81 
     82     /* Copy partition entries */
     83     memcpy(mbr.partitions, parts, sizeof(partition_entry_t) * 4);
     84 
     85     /* Set signature */
     86     mbr.signature = MBR_SIGNATURE;
     87 
     88     /* Write MBR */
     89     if (ata_write_sectors(bus, drive, 0, 1, &mbr) != ATA_OK) {
     90         return -1;
     91     }
     92 
     93     return 0;
     94 }
     95 
     96 int partition_has_mbr(uint8_t bus, uint8_t drive) {
     97     mbr_t mbr;
     98 
     99     if (ata_read_sectors(bus, drive, 0, 1, &mbr) != ATA_OK) {
    100         return 0;
    101     }
    102 
    103     return mbr.signature == MBR_SIGNATURE;
    104 }
    105 
    106 int partition_create_luajitos_layout(uint8_t bus, uint8_t drive, uint32_t boot_size_mb) {
    107     /* Get total disk size */
    108     ata_drive_info_t *info = ata_get_drive_info(bus, drive);
    109     if (!info || !info->present) {
    110         return -1;
    111     }
    112 
    113     uint32_t total_sectors = info->sectors;
    114     uint32_t boot_sectors = boot_size_mb * 2048;  /* 2048 sectors per MB */
    115 
    116     /* Boot partition starts at sector 2048 (1MB offset for alignment) */
    117     uint32_t boot_start = 2048;
    118 
    119     /* Encrypted partition starts after boot */
    120     uint32_t encrypted_start = boot_start + boot_sectors;
    121     uint32_t encrypted_sectors = total_sectors - encrypted_start;
    122 
    123     if (encrypted_start >= total_sectors) {
    124         terminal_writestring("[PART] Error: Disk too small for layout\n");
    125         return -1;
    126     }
    127 
    128     {
    129         char dbg[100];
    130         snprintf(dbg, sizeof(dbg), "[PART] Creating layout: boot=%dMB @%d, encrypted @%d (%d sectors)\n",
    131                  (int)boot_size_mb, (int)boot_start, (int)encrypted_start, (int)encrypted_sectors);
    132         terminal_writestring(dbg);
    133     }
    134 
    135     /* Build partition table */
    136     partition_entry_t parts[4];
    137     memset(parts, 0, sizeof(parts));
    138 
    139     /* Partition 1: Boot (FAT16, bootable) */
    140     parts[0].bootable = 0x80;
    141     lba_to_chs(boot_start, &parts[0].start_head, &parts[0].start_sector, &parts[0].start_cyl);
    142     parts[0].type = PART_TYPE_FAT16;
    143     lba_to_chs(boot_start + boot_sectors - 1, &parts[0].end_head, &parts[0].end_sector, &parts[0].end_cyl);
    144     parts[0].lba_start = boot_start;
    145     parts[0].sector_count = boot_sectors;
    146 
    147     /* Partition 2: Encrypted data (LuajitOS type) */
    148     parts[1].bootable = 0x00;
    149     lba_to_chs(encrypted_start, &parts[1].start_head, &parts[1].start_sector, &parts[1].start_cyl);
    150     parts[1].type = PART_TYPE_LUAJITOS;
    151     lba_to_chs(encrypted_start + encrypted_sectors - 1, &parts[1].end_head, &parts[1].end_sector, &parts[1].end_cyl);
    152     parts[1].lba_start = encrypted_start;
    153     parts[1].sector_count = encrypted_sectors;
    154 
    155     /* Write partition table */
    156     if (partition_write_table(bus, drive, parts) != 0) {
    157         terminal_writestring("[PART] Error: Failed to write partition table\n");
    158         return -1;
    159     }
    160 
    161     terminal_writestring("[PART] Partition table created successfully\n");
    162     return 0;
    163 }
    164 
    165 int partition_get_info(uint8_t bus, uint8_t drive, int index, partition_info_t *info) {
    166     if (index < 0 || index >= 4 || !info) {
    167         return -1;
    168     }
    169 
    170     partition_info_t parts[4];
    171     if (partition_read_table(bus, drive, parts) != 0) {
    172         return -1;
    173     }
    174 
    175     if (!parts[index].exists) {
    176         return -1;
    177     }
    178 
    179     *info = parts[index];
    180     return 0;
    181 }
    182 
    183 uint32_t partition_get_start(uint8_t bus, uint8_t drive, int index) {
    184     partition_info_t info;
    185     if (partition_get_info(bus, drive, index, &info) != 0) {
    186         return 0;
    187     }
    188     return info.start_lba;
    189 }
    190 
    191 uint32_t partition_get_size(uint8_t bus, uint8_t drive, int index) {
    192     partition_info_t info;
    193     if (partition_get_info(bus, drive, index, &info) != 0) {
    194         return 0;
    195     }
    196     return info.sector_count;
    197 }
    198 
    199 /* ============================================================================
    200  * Lua Bindings
    201  * ========================================================================= */
    202 
    203 #include "include/lua.h"
    204 #include "include/lauxlib.h"
    205 
    206 /* partition.readTable(bus, drive) -> table or nil */
    207 static int lua_partition_read_table(lua_State *L) {
    208     int bus = luaL_checkinteger(L, 1);
    209     int drive = luaL_checkinteger(L, 2);
    210 
    211     partition_info_t parts[4];
    212     if (partition_read_table(bus, drive, parts) != 0) {
    213         lua_pushnil(L);
    214         return 1;
    215     }
    216 
    217     lua_newtable(L);
    218     for (int i = 0; i < 4; i++) {
    219         lua_newtable(L);
    220         lua_pushboolean(L, parts[i].exists);
    221         lua_setfield(L, -2, "exists");
    222         lua_pushboolean(L, parts[i].bootable);
    223         lua_setfield(L, -2, "bootable");
    224         lua_pushinteger(L, parts[i].type);
    225         lua_setfield(L, -2, "type");
    226         lua_pushinteger(L, parts[i].start_lba);
    227         lua_setfield(L, -2, "startLba");
    228         lua_pushinteger(L, parts[i].sector_count);
    229         lua_setfield(L, -2, "sectorCount");
    230         lua_pushinteger(L, parts[i].size_mb);
    231         lua_setfield(L, -2, "sizeMb");
    232         lua_rawseti(L, -2, i + 1);
    233     }
    234 
    235     return 1;
    236 }
    237 
    238 /* partition.hasMbr(bus, drive) -> boolean */
    239 static int lua_partition_has_mbr(lua_State *L) {
    240     int bus = luaL_checkinteger(L, 1);
    241     int drive = luaL_checkinteger(L, 2);
    242 
    243     lua_pushboolean(L, partition_has_mbr(bus, drive));
    244     return 1;
    245 }
    246 
    247 /* partition.createLayout(bus, drive, bootSizeMb) -> boolean */
    248 static int lua_partition_create_layout(lua_State *L) {
    249     int bus = luaL_checkinteger(L, 1);
    250     int drive = luaL_checkinteger(L, 2);
    251     int boot_size_mb = luaL_optinteger(L, 3, 16);
    252 
    253     int result = partition_create_luajitos_layout(bus, drive, boot_size_mb);
    254     lua_pushboolean(L, result == 0);
    255     return 1;
    256 }
    257 
    258 /* partition.getInfo(bus, drive, index) -> table or nil */
    259 static int lua_partition_get_info(lua_State *L) {
    260     int bus = luaL_checkinteger(L, 1);
    261     int drive = luaL_checkinteger(L, 2);
    262     int index = luaL_checkinteger(L, 3);
    263 
    264     partition_info_t info;
    265     if (partition_get_info(bus, drive, index, &info) != 0) {
    266         lua_pushnil(L);
    267         return 1;
    268     }
    269 
    270     lua_newtable(L);
    271     lua_pushboolean(L, info.exists);
    272     lua_setfield(L, -2, "exists");
    273     lua_pushboolean(L, info.bootable);
    274     lua_setfield(L, -2, "bootable");
    275     lua_pushinteger(L, info.type);
    276     lua_setfield(L, -2, "type");
    277     lua_pushinteger(L, info.start_lba);
    278     lua_setfield(L, -2, "startLba");
    279     lua_pushinteger(L, info.sector_count);
    280     lua_setfield(L, -2, "sectorCount");
    281     lua_pushinteger(L, info.size_mb);
    282     lua_setfield(L, -2, "sizeMb");
    283 
    284     return 1;
    285 }
    286 
    287 static const luaL_Reg partition_funcs[] = {
    288     {"readTable", lua_partition_read_table},
    289     {"hasMbr", lua_partition_has_mbr},
    290     {"createLayout", lua_partition_create_layout},
    291     {"getInfo", lua_partition_get_info},
    292     {NULL, NULL}
    293 };
    294 
    295 int luaopen_partition(lua_State *L) {
    296     luaL_newlib(L, partition_funcs);
    297 
    298     /* Add partition type constants */
    299     lua_pushinteger(L, PART_TYPE_EMPTY);
    300     lua_setfield(L, -2, "TYPE_EMPTY");
    301     lua_pushinteger(L, PART_TYPE_FAT16);
    302     lua_setfield(L, -2, "TYPE_FAT16");
    303     lua_pushinteger(L, PART_TYPE_LUAJITOS);
    304     lua_setfield(L, -2, "TYPE_LUAJITOS");
    305 
    306     return 1;
    307 }