@@ -151,11 +151,19 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
151151 const max_partition_lba = secondary_pe_array_lba - 1 ;
152152
153153 // 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 );
156166
157- var next_lba : u64 = 34 ;
158- for (table .partitions [0.. ], partition_entries [0.. table .partitions .len ], 0.. ) | partition , * entry , i | {
159167 const offset = partition .offset orelse next_lba * block_size ;
160168 const size = partition .size orelse if (i == table .partitions .len - 1 )
161169 ((max_partition_lba + 1 ) * block_size ) - offset
@@ -175,8 +183,8 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
175183 const start_lba = @divExact (offset , block_size );
176184 const end_lba = @divExact (size + offset , block_size ) - 1 ;
177185
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 });
180188 return error .ConfigurationError ;
181189 }
182190
@@ -185,19 +193,26 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
185193 return error .ConfigurationError ;
186194 }
187195
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 );
192200 // 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 );
194206
195207 var sub_view = try stream .slice (offset , size );
196208 try partition .contains .render (& sub_view );
197209
198210 next_lba = end_lba + 1 ;
211+ pe_ofs += 0x80 ;
199212 }
200213
214+ const pe_array_crc32 = pe_crc .final ();
215+
201216 // create the protective mbr
202217 var mbr : MbrPartTable = .{
203218 .bootloader = null ,
@@ -221,7 +236,7 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
221236 std .mem .writeInt (u64 , gpt_header [0x20.. 0x28], secondary_pth_lba , .little ); // LBA of other header
222237 std .mem .writeInt (u64 , gpt_header [0x28.. 0x30], 34 , .little ); // First usable LBA
223238 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] );
225240 std .mem .writeInt (u64 , gpt_header [0x48.. 0x50], 2 , .little ); // First LBA of the partition entry array
226241 std .mem .writeInt (u32 , gpt_header [0x50.. 0x54], 0x80 , .little ); // Number of partition entries
227242 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
233248 std .mem .writeInt (u64 , backup_gpt_header [0x20.. 0x28], 1 , .little ); // LBA of other header
234249 std .mem .writeInt (u64 , backup_gpt_header [0x48.. 0x50], secondary_pe_array_lba , .little ); // First LBA of the backup partition entry array
235250
236- const pe_array_crc32 = std .hash .Crc32 .hash (& pe_blocks );
237251 std .mem .writeInt (u32 , gpt_header [0x58.. 0x5c], pe_array_crc32 , .little ); // CRC32 of partition entries array
238252 std .mem .writeInt (u32 , backup_gpt_header [0x58.. 0x5c], pe_array_crc32 , .little ); // CRC32 of partition entries array
239253
@@ -246,18 +260,9 @@ pub fn render(table: *PartTable, stream: *dim.BinaryStream) dim.Content.RenderEr
246260 // write everything we generated to disk
247261 try mbr .render (stream );
248262 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 );
251263 try stream .write (block_size * secondary_pth_lba , & backup_gpt_header_block );
252264}
253265
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-
261266pub const Guid = extern struct {
262267 time_low : u32 , // LE
263268 time_mid : u16 , // LE
@@ -282,6 +287,8 @@ pub const Guid = extern struct {
282287 }
283288
284289 pub fn parse (str : [36 ]u8 ) ! Guid {
290+ @setEvalBranchQuota (16384 );
291+
285292 const tl_hex = str [0.. 8];
286293 if (str [8 ] != '-' ) return error .MissingSeparator ;
287294 const tm_hex = str [9.. 13];
@@ -292,48 +299,37 @@ pub const Guid = extern struct {
292299 if (str [23 ] != '-' ) return error .MissingSeparator ;
293300 const node_hex = str [24.. 36];
294301
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 );
300312
301- const tl_le = @byteSwap (tl_be );
302- const tm_le = @byteSwap (tm_be );
303- const th_le = @byteSwap (th_be );
304313 const csh = cs_bytes [0 ];
305314 const csl = cs_bytes [1 ];
306315
307316 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 ,
311320 .clock_seq_high_and_reserved = csh ,
312321 .clock_seq_low = csl ,
313322 .node = node_bytes ,
314323 };
315324 }
316325
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 ;
337333 }
338334};
339335
@@ -364,33 +360,23 @@ pub const Partition = struct {
364360// TODO fill from https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
365361pub const known_types = std .StaticStringMap (Guid ).initComptime (.{
366362 .{ "unused" , Guid .parse ("00000000-0000-0000-0000-000000000000" .* ) catch unreachable },
367- .{ "efi-system" , Guid .parse ("C12A7328-F81F-11D2-BA4B-00A0C93EC93B" .* ) catch unreachable },
368- });
369363
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 },
372367
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 },
375370
376- // pub const windows_recovery: Guid = .{};
371+ .{ " windows_recovery" , Guid . parse ( "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC" .* ) catch unreachable },
377372
378- // pub const plan9: Guid = .{};
373+ .{ " plan9" , Guid . parse ( "C91818F9-8025-47AF-89D2-F030D7000C2C" .* ) catch unreachable },
379374
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+ });
394380
395381pub fn stringToName (name : []const u8 ) ! [36 ]u16 {
396382 var buf : [36 ]u16 = @splat (0 );
0 commit comments