#Alignment in a packed struct

1 messages · Page 1 of 1 (latest)

fickle mortar
#

I'm trying to cast an address (provided as a u64 value) to a pointer to a packed struct that represents a firmware table. I've defined my struct like this:

pub const Rsdp2Descriptor = packed struct {
    signature: u64,       // originally [8]u8
    checksum: u8,
    oem_id: u48,          // originally [6]u8
    revision: u8,
    rsdt_address: u32,
    length: u32,
    xsdt_address: u64,
    extended_checksum: u8,
    reserved: u24,        // originally [3]u8
};

I chose to use integer types instead of byte arrays because using [8]u8, [6]u8, etc. in a packed struct is apparently not allowed in Zig.

However, this approach causes my struct to have a u64 alignment. When I cast an address (e.g., 0x777e014, appropriately converted to a virtual address) to a pointer to this struct, I get an alignment safety check error.

I can't use the align attribute on individual fields of a packed struct either. How can I work around this alignment safety issue while still being able to interpret the incoming data correctly?

crimson frigate
#

The fix is to not use a packed struct, a packed struct is explicitly represented as a single integer (here u288); use an extern struct with those non-power-of-two integers replaced by arrays

fickle mortar
#

Thanks for the response. So I tried:

pub const Rsdp2Descriptor = extern struct {
    signature: [8]u8,
    checksum: u8,
    oem_id: [6]u8, // originally [6]u8
    revision: u8,
    rsdt_address: u32,
    length: u32,
    xsdt_address: u64,
    extended_checksum: u8,
    reserved: [3]u8, // originally [3]u8
    pub fn init() *Rsdp2Descriptor {
        if (rsdp_request.response) |response| {
            // convert the address to virtual
            const responseVirt = paging.physToVirtRaw(response.address);
            // it will panic at the following line:
            const self = @as(*Rsdp2Descriptor, @ptrFromInt(responseVirt));
        }
    }
};

But I still have the alignment issue where I can't cast that address as a pointer to my struct. Any pointers?

crimson frigate
#

change the alignment of the fields so that its natural alignment is lower

fickle mortar
#

will I need to do something like align(1) on all of the fields? I'm not sure what value of alignment I should use. Sorry this is my first time tackling this kind of problem. 😅

crimson frigate
#

you should align(1) all of the fields if you expect the struct to not be aligned

fickle mortar
#

if that's the best way to do it, then okay

#

i just know that I'm gonna see someone else's implementation and realise how I was going in the complete wrong direction

#

okay maybe not lol because I just checked a reference implementation

#

but I think I'll mark this as solved now.