Close

From the Directory to the File

A project log for OSI SD Card Operating System (OSISDOS)

Ohio Scientific / UK101 SD Card based Operating System under Multicomp FPGA Computer

land-boardscomland-boards.com 08/05/2020 at 22:390 Comments

In the previous log I got the directory to read into the RAMDISK space. This step will go from the directory to a file. This page gives a nice synopsis.

From my previous log, the directory on my SD card looks like:

Directory entries are in 32-byte blocks, for instance the RAMTEST.BAS entry has:

The Microsoft Extensible Firmware Initiative FAT32 File System Specification provides additional information in tabular form

NameOffset (byte)Size (bytes)Description
DIR_Name011Short name.
<RAMTEST BAS>
DIR_Attr111File attributes:
ATTR_READ_ONLY 0x01
ATTR_HIDDEN 0x02
ATTR_SYSTEM 0x04
ATTR_VOLUME_ID 0x08
ATTR_DIRECTORY 0x10
ATTR_ARCHIVE 0x20
ATTR_LONG_NAME 
ATTR_READ_ONLY | 
ATTR_HIDDEN | 
ATTR_SYSTEM | 
ATTR_VOLUME_ID 
The upper two bits of the attribute byte are reserved
and  should always be set to 0 when a file is created
and  never modified or looked at after that.
<0x20>
DIR_NTRes121Reserved for use by Windows NT. 
Set value to 0 when a file is created and never modify
or look at it after that.
<0x00>
DIR_CrtTimeTenth131Millisecond stamp at file creation time. 
This field actually contains a count of tenths of a second. 
The granularity of the seconds part of DIR_CrtTime is
2 seconds  so this field is a count of tenths of
a second and its  valid value range is 0-199 inclusive.
<0xA7>
DIR_FstClusHI202High word of this entry’s first cluster number 
(always 0 for a FAT12 or FAT16 volume).
<0x0000>
DIR_WrtTime222Time of last write. Note that file creation  is considered a write. <0x00DD>
DIR_WrtDate242Date of last write. Note that file creation is considered a write. <0xF9A4>
DIR_FstClusLO262Low word of this entry’s first cluster number.
<0x0007> = 7 dec
DIR_FileSize28432-bit DWORD holding this file’s size in bytes.
<0x0000019C> = 412 dec

So, the cluster number for RAMTEST.BAS is 56. From the boot record, there are 8 sectors per cluster. 

13      BPB_SecPerClus        Number of sectors per cluster (1)        Must be one of 1, 2, 4, 8, 16, 32, 64, 128.        A cluster should have at most 32768 bytes.         In rare cases 65536 is OK.        <0x08> = 8 sectors per clusters

That means the file starts at cluster 7 * 8 = 56. This should be relative to the FirstDataSector calculated above to be 32,768. So the first sector number for RAMTEST.BAS should be at 32,768+56=32,824. However, the file is actually 16 sectors earlier at sector 32,808. Must be an offset of 2 clusters?

Here's the answer:

Looking at the hex dump

I get the same result from the BASIC program. LBA1 = 0x80 which is 32768.

RUN
LBA0 ? 40
LBA1 ? 128
LBA2 ? 0
SD CTRLR STAT = 128
20 31 30 30 20 52 45 4D 20 54 45 53 54 20 55 50   100 REM TEST UP
50 45 52 20 4D 45 4D 4F 52 59 0D 0A 20 31 31 30  PER MEMORY.. 110
20 52 45 4D 20 55 50 50 45 52 20 4D 45 4D 4F 52   REM UPPER MEMOR
59 20 49 53 20 34 4B 42 20 46 52 4F 4D 20 24 45  Y IS 4KB FROM $E
30 30 30 2D 24 45 46 46 46 20 28 35 37 33 34 34  000-$EFFF (57344
2D 36 31 34 33 39 20 44 45 43 29 0D 0A 20 31 32  -61439 DEC).. 12
30 20 53 3D 35 37 33 34 34 0D 0A 20 31 33 30 20  0 S=57344.. 130
45 3D 36 31 34 33 39 0D 0A 20 32 30 30 20 52 45  E=61439.. 200 RE
4D 20 46 49 4C 4C 20 4D 45 4D 4F 52 59 0D 0A 20  M FILL MEMORY..
32 31 30 20 50 3D 30 0D 0A 20 32 32 30 20 46 4F  210 P=0.. 220 FO
52 20 41 3D 53 20 54 4F 20 45 0D 0A 20 32 33 30  R A=S TO E.. 230
20 50 4F 4B 45 20 41 2C 50 0D 0A 20 32 34 30 20   POKE A,P.. 240
50 3D 50 2B 31 0D 0A 20 32 35 30 20 50 3D 50 20  P=P+1.. 250 P=P
41 4E 44 20 32 35 35 0D 0A 20 32 36 30 20 4E 45  AND 255.. 260 NE
58 54 20 41 0D 0A 20 33 30 30 20 52 45 4D 20 56  XT A.. 300 REM V
45 52 49 46 59 20 46 49 4C 4C 45 44 20 4D 45 4D  ERIFY FILLED MEM
4F 52 59 0D 0A 20 33 31 30 20 58 3D 30 0D 0A 20  ORY.. 310 X=0..
33 32 30 20 46 4F 52 20 41 3D 53 20 54 4F 20 45  320 FOR A=S TO E
0D 0A 20 33 33 30 20 50 3D 50 45 45 4B 28 41 29  .. 330 P=PEEK(A)
0D 0A 20 33 34 30 20 49 46 20 50 3C 3E 58 20 47  .. 340 IF P<>X G
4F 54 4F 20 35 30 30 0D 0A 20 33 35 30 20 58 3D  OTO 500.. 350 X=
58 2B 31 0D 0A 20 33 36 30 20 58 3D 58 20 41 4E  X+1.. 360 X=X AN
44 20 32 35 35 0D 0A 20 33 37 30 20 4E 45 58 54  D 255.. 370 NEXT
20 41 0D 0A 20 33 38 30 20 45 4E 44 0D 0A 20 35   A.. 380 END.. 5
30 30 20 50 52 49 4E 54 22 45 52 52 4F 52 22 0D  00 PRINT"ERROR".
0A 20 35 31 30 20 45 4E 44 0D 0A 20 00 00 00 00  . 510 END.. ....
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

So, the sector number of a particular file on the SD Card from the directory is:

LBA = FirstDataSector  + ((((DIR_FstClusHI << 16) + (DIR_FstClusHLo)) - 2) * BPB_SecPerClus )

For RAMTEST.BAS:

So, the LBA for RAMTEST.BAS should be:

= 32,768 + * ( ( (0x0000<<16) + (0x0007) ) - 2) * 8)

= 32,768+40

= 32,808

Which is correct!

C Source code is here.

Discussions