@@ -151,11 +151,19 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
151
151
const max_partition_lba = secondary_pe_array_lba - 1 ;
152
152
153
153
// create the partition entry array, lba 2 through 33
154
- var pe_blocks : [block_size * 32 ]u8 = @splat (0 );
155
- const partition_entries = std .mem .bytesAsSlice ([0x80 ]u8 , & pe_blocks );
154
+ var pe_block : [0x80 ]u8 = undefined ;
155
+ var pe_crc : std.hash.Crc32 = .init ();
156
+
157
+ var pe_ofs : usize = 0 ;
158
+
159
+ var next_lba : u64 = 2 + (std .math .divCeil (u64 , table .partitions .len * 0x80 , block_size ) catch | e | switch (e ) {
160
+ error .DivisionByZero = > unreachable ,
161
+ inline else = > | e2 | return e2 ,
162
+ });
163
+ const pe_end_plus_one_lba = next_lba ;
164
+ for (table .partitions [0.. ], 0.. ) | partition , i | {
165
+ @memset (& pe_block , 0 );
156
166
157
- var next_lba : u64 = 34 ;
158
- for (table .partitions [0.. ], partition_entries [0.. table .partitions .len ], 0.. ) | partition , * entry , i | {
159
167
const offset = partition .offset orelse next_lba * block_size ;
160
168
const size = partition .size orelse if (i == table .partitions .len - 1 )
161
169
((max_partition_lba + 1 ) * block_size ) - offset
@@ -175,8 +183,8 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
175
183
const start_lba = @divExact (offset , block_size );
176
184
const end_lba = @divExact (size + offset , block_size ) - 1 ;
177
185
178
- if (start_lba <= 33 ) {
179
- std .log .err ("partition {} overlaps with gpt. the partition begins at lba {}, and the gpt ends at {}" , .{ i + 1 , start_lba , 33 });
186
+ if (start_lba <= pe_end_plus_one_lba ) {
187
+ std .log .err ("partition {} overlaps with gpt. the partition begins at lba {}, and the gpt ends at {}" , .{ i + 1 , start_lba , pe_end_plus_one_lba });
180
188
return error .ConfigurationError ;
181
189
}
182
190
@@ -185,19 +193,26 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
185
193
return error .ConfigurationError ;
186
194
}
187
195
188
- entry [0x00.. 0x10].* = @bitCast (partition .type );
189
- entry [0x10 .. 0x20] .* = @bitCast (partition .part_id orelse Guid .rand (random ));
190
- std .mem .writeInt (u64 , entry [0x20.. 0x28], start_lba , .little );
191
- std .mem .writeInt (u64 , entry [0x28.. 0x30], end_lba , .little );
196
+ pe_block [0x00.. 0x10].* = @bitCast (partition .type );
197
+ (partition .part_id orelse Guid .rand (random )). write ( pe_block [0x10 .. 0x20] );
198
+ std .mem .writeInt (u64 , pe_block [0x20.. 0x28], start_lba , .little );
199
+ std .mem .writeInt (u64 , pe_block [0x28.. 0x30], end_lba , .little );
192
200
// TODO attributes
193
- entry [0x38.. ].* = @bitCast (partition .name );
201
+ pe_block [0x38.. ].* = @bitCast (partition .name );
202
+
203
+ pe_crc .update (& pe_block );
204
+ try stream .write (block_size * 2 + pe_ofs , & pe_block );
205
+ try stream .write (block_size * secondary_pe_array_lba + pe_ofs , & pe_block );
194
206
195
207
var sub_view = try stream .slice (offset , size );
196
208
try partition .contains .render (& sub_view );
197
209
198
210
next_lba = end_lba + 1 ;
211
+ pe_ofs += 0x80 ;
199
212
}
200
213
214
+ const pe_array_crc32 = pe_crc .final ();
215
+
201
216
// create the protective mbr
202
217
var mbr : MbrPartTable = .{
203
218
.bootloader = null ,
@@ -221,7 +236,7 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
221
236
std .mem .writeInt (u64 , gpt_header [0x20.. 0x28], secondary_pth_lba , .little ); // LBA of other header
222
237
std .mem .writeInt (u64 , gpt_header [0x28.. 0x30], 34 , .little ); // First usable LBA
223
238
std .mem .writeInt (u64 , gpt_header [0x30.. 0x38], max_partition_lba , .little ); // Last usable LBA
224
- gpt_header [0x38 .. 0x48] .* = @bitCast (table .disk_id orelse Guid .rand (random ));
239
+ (table .disk_id orelse Guid .rand (random )). write ( gpt_header [0x38 .. 0x48] );
225
240
std .mem .writeInt (u64 , gpt_header [0x48.. 0x50], 2 , .little ); // First LBA of the partition entry array
226
241
std .mem .writeInt (u32 , gpt_header [0x50.. 0x54], 0x80 , .little ); // Number of partition entries
227
242
std .mem .writeInt (u32 , gpt_header [0x54.. 0x58], 0x80 , .little ); // Size of a partition entry
@@ -233,7 +248,6 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
233
248
std .mem .writeInt (u64 , backup_gpt_header [0x20.. 0x28], 1 , .little ); // LBA of other header
234
249
std .mem .writeInt (u64 , backup_gpt_header [0x48.. 0x50], secondary_pe_array_lba , .little ); // First LBA of the backup partition entry array
235
250
236
- const pe_array_crc32 = std .hash .Crc32 .hash (& pe_blocks );
237
251
std .mem .writeInt (u32 , gpt_header [0x58.. 0x5c], pe_array_crc32 , .little ); // CRC32 of partition entries array
238
252
std .mem .writeInt (u32 , backup_gpt_header [0x58.. 0x5c], pe_array_crc32 , .little ); // CRC32 of partition entries array
239
253
@@ -246,18 +260,9 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
246
260
// write everything we generated to disk
247
261
try mbr .render (stream );
248
262
try stream .write (block_size , & gpt_header_block );
249
- try stream .write (block_size * 2 , & pe_blocks );
250
- try stream .write (block_size * secondary_pe_array_lba , & pe_blocks );
251
263
try stream .write (block_size * secondary_pth_lba , & backup_gpt_header_block );
252
264
}
253
265
254
- fn crc32Header (header : [0x5c ]u8 ) u32 {
255
- var crc32 = std .hash .Crc32 .init ();
256
- crc32 .update (header [0x00.. 0x14]);
257
- crc32 .update (header [0x18.. ]);
258
- return crc32 .final ();
259
- }
260
-
261
266
pub const Guid = extern struct {
262
267
time_low : u32 , // LE
263
268
time_mid : u16 , // LE
@@ -282,6 +287,8 @@ pub const Guid = extern struct {
282
287
}
283
288
284
289
pub fn parse (str : [36 ]u8 ) ! Guid {
290
+ @setEvalBranchQuota (16384 );
291
+
285
292
const tl_hex = str [0.. 8];
286
293
if (str [8 ] != '-' ) return error .MissingSeparator ;
287
294
const tm_hex = str [9.. 13];
@@ -292,48 +299,37 @@ pub const Guid = extern struct {
292
299
if (str [23 ] != '-' ) return error .MissingSeparator ;
293
300
const node_hex = str [24.. 36];
294
301
295
- const tl_be : u32 = @bitCast (try hexToBytes (tl_hex .* ));
296
- const tm_be : u16 = @bitCast (try hexToBytes (tm_hex .* ));
297
- const th_be : u16 = @bitCast (try hexToBytes (th_hex .* ));
298
- const cs_bytes = try hexToBytes (cs_hex .* );
299
- const node_bytes = try hexToBytes (node_hex .* );
302
+ const tl : u32 = try std .fmt .parseInt (u32 , tl_hex , 16 );
303
+ const tm : u16 = try std .fmt .parseInt (u16 , tm_hex , 16 );
304
+ const th : u16 = try std .fmt .parseInt (u16 , th_hex , 16 );
305
+ const cs : u16 = try std .fmt .parseInt (u16 , cs_hex , 16 );
306
+ const node : u48 = try std .fmt .parseInt (u48 , node_hex , 16 );
307
+
308
+ var cs_bytes : [2 ]u8 = undefined ;
309
+ std .mem .writeInt (u16 , & cs_bytes , cs , .big );
310
+ var node_bytes : [6 ]u8 = undefined ;
311
+ std .mem .writeInt (u48 , & node_bytes , node , .big );
300
312
301
- const tl_le = @byteSwap (tl_be );
302
- const tm_le = @byteSwap (tm_be );
303
- const th_le = @byteSwap (th_be );
304
313
const csh = cs_bytes [0 ];
305
314
const csl = cs_bytes [1 ];
306
315
307
316
return Guid {
308
- .time_low = tl_le ,
309
- .time_mid = tm_le ,
310
- .time_high_and_version = th_le ,
317
+ .time_low = tl ,
318
+ .time_mid = tm ,
319
+ .time_high_and_version = th ,
311
320
.clock_seq_high_and_reserved = csh ,
312
321
.clock_seq_low = csl ,
313
322
.node = node_bytes ,
314
323
};
315
324
}
316
325
317
- fn HexToBytesType (comptime T : type ) type {
318
- const ti = @typeInfo (T );
319
- const len = @divExact (ti .array .len , 2 );
320
- return @Type (.{ .array = .{
321
- .len = len ,
322
- .child = u8 ,
323
- .sentinel_ptr = null ,
324
- } });
325
- }
326
-
327
- fn hexToBytes (hex : anytype ) ! HexToBytesType (@TypeOf (hex )) {
328
- var ret : [@divExact (hex.len , 2 )]u8 = undefined ;
329
-
330
- for (0.. ret .len ) | i | {
331
- const hi = try std .fmt .charToDigit (hex [i * 2 ], 16 );
332
- const lo = try std .fmt .charToDigit (hex [i * 2 + 1 ], 16 );
333
- ret [i ] = (hi << 4 ) | lo ;
334
- }
335
-
336
- return ret ;
326
+ pub fn write (guid : Guid , buf : * [16 ]u8 ) void {
327
+ std .mem .writeInt (u32 , buf [0.. 4], guid .time_low , .little );
328
+ std .mem .writeInt (u16 , buf [4.. 6], guid .time_mid , .little );
329
+ std .mem .writeInt (u16 , buf [6.. 8], guid .time_high_and_version , .little );
330
+ buf [8 ] = guid .clock_seq_high_and_reserved ;
331
+ buf [9 ] = guid .clock_seq_low ;
332
+ buf [10.. 16].* = guid .node ;
337
333
}
338
334
};
339
335
@@ -364,33 +360,23 @@ pub const Partition = struct {
364
360
// TODO fill from https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
365
361
pub const known_types = std .StaticStringMap (Guid ).initComptime (.{
366
362
.{ "unused" , Guid .parse ("00000000-0000-0000-0000-000000000000" .* ) catch unreachable },
367
- .{ "efi-system" , Guid .parse ("C12A7328-F81F-11D2-BA4B-00A0C93EC93B" .* ) catch unreachable },
368
- });
369
363
370
- // struct {
371
- // pub const unused: Guid = .{};
364
+ .{ "esp" , Guid .parse ("C12A7328-F81F-11D2-BA4B-00A0C93EC93B" .* ) catch unreachable },
365
+ .{ "legacy_mbr" , Guid .parse ("024DEE41-33E7-11D3-9D69-0008C781F39F" .* ) catch unreachable },
366
+ .{ "bios_boot" , Guid .parse ("21686148-6449-6E6F-744E-656564454649" .* ) catch unreachable },
372
367
373
- // pub const microsoft_basic_data: Guid = .{};
374
- // pub const microsoft_reserved: Guid = .{};
368
+ .{ " microsoft_basic_data" , Guid . parse ( "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" .* ) catch unreachable },
369
+ .{ " microsoft_reserved" , Guid . parse ( "E3C9E316-0B5C-4DB8-817D-F92DF00215AE" .* ) catch unreachable },
375
370
376
- // pub const windows_recovery: Guid = .{};
371
+ .{ " windows_recovery" , Guid . parse ( "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC" .* ) catch unreachable },
377
372
378
- // pub const plan9: Guid = .{};
373
+ .{ " plan9" , Guid . parse ( "C91818F9-8025-47AF-89D2-F030D7000C2C" .* ) catch unreachable },
379
374
380
- // pub const linux_swap: Guid = .{};
381
- // pub const linux_fs: Guid = .{};
382
- // pub const linux_reserved: Guid = .{};
383
- // pub const linux_lvm: Guid = .{};
384
- // };
385
-
386
- pub fn nameLiteral (comptime name : []const u8 ) [36 ]u16 {
387
- return comptime blk : {
388
- var buf : [36 ]u16 = undefined ;
389
- const len = std .unicode .utf8ToUtf16Le (& buf , name ) catch | err | @compileError (@tagName (err ));
390
- @memset (buf [len .. ], 0 );
391
- break :blk & buf ;
392
- };
393
- }
375
+ .{ "linux_swap" , Guid .parse ("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F" .* ) catch unreachable },
376
+ .{ "linux_fs" , Guid .parse ("0FC63DAF-8483-4772-8E79-3D69D8477DE4" .* ) catch unreachable },
377
+ .{ "linux_reserved" , Guid .parse ("8DA63339-0007-60C0-C436-083AC8230908" .* ) catch unreachable },
378
+ .{ "linux_lvm" , Guid .parse ("E6D6D379-F507-44C2-A23C-238F2A3DF928" .* ) catch unreachable },
379
+ });
394
380
395
381
pub fn stringToName (name : []const u8 ) ! [36 ]u16 {
396
382
var buf : [36 ]u16 = @splat (0 );
0 commit comments