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 }