FAT BPB and little endian reversal

510 views Asked by At

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!

2

There are 2 answers

0
uesp On BEST ANSWER

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.

3
JS1 On

First of all, this line:

printf("BPB_BytesPerSec = 0x%02x%02x\n",BPB_BytesPerSec[0], BPB_BytesPerSec[1]);

is printing the value out in big endian format. If it prints 0x0002 here, the actual value would be 0x0200 in little endian.

As for the BS_jmpBoot value, according to this site:

The first three bytes EB 3C and 90 disassemble to JMP SHORT 3C NOP. (The 3C value may be different.) The reason for this is to jump over the disk format information (the BPB and EBPB). Since the first sector of the disk is loaded into ram at location 0x0000:0x7c00 and executed, without this jump, the processor would attempt to execute data that isn't code.

In other words, the first 3 bytes are opcodes which are three separate bytes, not one little endian value.