@@ -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