Search code examples
cdiskendiannessfat

FAT BPB and little endian reversal


My CPU is little endian, which documentation has told me conforms to the byte-order of the FAT specification. Why then, am I getting a valid address for the BS_jmpBoot, bytes 0-3 of first sector, but not getting a valid number for BPB_BytesPerSec, bytes 11-12 of the first sector.

116         int fd = open (diskpath, O_RDONLY, S_IROTH);
117 
118         read (fd, BS_jmpBoot, 3);
119         printf("BS_jmpBoot = 0x%02x%02x%02x\n", BS_jmpBoot[0], S_jmpBoot[1], S_jmpBoot[2]);
120 
121         read (fd, OEMName, 8);
122         OEMName[8] = '\0';
123         printf("OEMName = %s\n", OEMName);
124 
125         read (fd, BPB_BytesPerSec, 2);
126         printf("BPB_BytesPerSec = 0x%02x%02x\n",BPB_BytesPerSec[0], BPB_BytesPerSec[1]);

Yields

BS_jmpBoot = 0xeb5890                  //valid address, while 0x9058eb would not be
OEMName = MSDOS5.0
BPB_BytesPerSec = 0x0002               //Should be 0x0200

I would like figure out why BS_jmpBoot and OEMName print valid but BPB_BytesPerSec does not. If anyone could enlighten me I would be greatly appreciative.

Thanks

EDIT: Thanks for the help everyone, it was my types that were making everything go awry. I got it to work by writing the bytes to an unsigned short, as uesp suggested(kinda), but I would still like to know why this didn't work:

            unsigned char BPB_BytesPerSec[2];
...
125         read (fd, BPB_BytesPerSec, 2);
126         printf("BPB_BytesPerSec = 0x%04x\n", *BPB_BytesPerSec);

yielded BPB_BytesPerSec = 0x0000

I would like to use char arrays to allocate the space because I want to be sure of the space I'm writing to on any machine; or should I not?

Thanks again!


Solution

  • You are reading BPB_BytesPerSec incorrectly. The structure of the Bpb is (from here):

    BYTE  BS_jmpBoot[3];
    BYTE  BS_OEMName[8];
    WORD  BPB_BytesPerSec;
    ...
    

    The first two fields are bytes so their endianness is irrelevant (I think). BPB_BytesPerSec is a WORD (assuming 2 bytes) so you should define/read it like:

    WORD BPB_BytesPerSec;            //Assuming WORD is defined on your system
    read (fd, &BPB_BytesPerSec, 2);
    printf("BPB_BytesPerSec = 0x%04x\n", BPB_BytesPerSec); 
    

    Since when you read the bytes directly you get 00 02, which is 0x0200 in little endian, you should correctly read BPB_BytesPerSec like this.