flat assembler
Message board for the users of flat assembler.

Index > OS Construction > make disc image with fasm

Author
Thread Post new topic Reply to topic
codelab



Joined: 03 Apr 2006
Posts: 16
Location: Denmark
codelab
Hi OS developer
This is a beta to deploy images with a file structure,

Can anyone tell me how a macro can process a filename like 'test.bin' to fatname: 'test bin' without storing this internally in db filename, since it needs to be put elsewhere ?

Sincerely C.


Code:
; Disc image macros
; to make a bootable [partitioned] disc image with flat file filesystem
; made to deploy image directly for OS developent
; todo: clear constants, filedatesupport, directory support ,limit check , process fatname
; betaversion by Lasse Bauer
;
; Usage: eg.
;
; DiscImage 32*1024,'masterboot.bin','bootsect.bin'                    ; to create a diskimage with no partitions do '' as 2nd parameter
; inject 'PM.SYS'    ,'P','M',' ',' ',' ',' ',' ',' ','S','Y','S'
; inject 'HELLO.BIN' ,'H','E','L','L','O',' ',' ',' ','B','I','N'
; inject 'DUMP.BIN'p ,'D','U','M','P',' ',' ',' ',' ','B','I','N'
; padclusters
;
;
;
; - compile with fasm, output is hdimag.img

format binary as 'img'

macro poke adr, bval { store byte bval at adr }
macro dpoke adr, wval { store word wval at adr }
macro lpoke adr, lval { store dword lval at adr }
macro hdoffset hdadress { rb hdadress-($-$$)}

macro inject name,fatname1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11
{
   ; store a file in image
   ; add new 32 byte root entry, update entry pointer
   ; update FAT's

   local fst,feof
fst:
   file name
feof:
   fsize =feof-fst
   startcluster=cluster

   repeat (fsize-1)/_sectorsize  ; or clustersize
       poke fat1+2*cluster+0,cluster+1      ;            ? ? ? ? 3
       poke fat1+2*cluster+1,0            ;            ? ? ? ? 3 0
       poke fat2+2*cluster+0,cluster+1      ;            ? ? ? ? 3
       poke fat2+2*cluster+1,0            ;            ? ? ? ? 3 0
       cluster=cluster+1
   end repeat


   dpoke fat1+2*cluster,0FFFFh
   dpoke fat2+2*cluster,0FFFFh
   cluster=cluster+1

   poke rootdirptr+00h,fatname1
   poke rootdirptr+01h,f2
   poke rootdirptr+02h,f3
   poke rootdirptr+03h,f4
   poke rootdirptr+04h,f5
   poke rootdirptr+05h,f6
   poke rootdirptr+06h,f7
   poke rootdirptr+07h,f8
   poke rootdirptr+08h,f9
   poke rootdirptr+09h,f10
   poke rootdirptr+0Ah,f11
;  tstamp...
;
;
    dpoke rootdirptr+26,startcluster
    lpoke rootdirptr+28,fsize
    rootdirptr=rootdirptr+32
    align _sectorsize

}

macro DiscImage lKIBsize,mbcode,bootcode
{
 KIBsize= lKIBsize
 _sectorsize=512
 startsector=0h
 _rootentries=0200h
 _sectorsperfat=0E7h
 _rssectorsbeforefat=02h

 zero:
 if mbcode<>''
   startsector=080h
   masterbootsector:
     file mbcode
     rb 446-($-masterbootsector)
   partitionentry:
     rb 4 * 16
     dw 0xAA55
     poke partitionentry+0,080h                  ; prim boot indicator
     poke partitionentry+1,002h                  ; starting head
    dpoke partitionentry+2,003h                  ; starting sector & cylinder
     poke partitionentry+4,004h                  ; partition type
     poke partitionentry+5,000h                  ; ending head
    dpoke partitionentry+6,03B30h                ; ending sector & cylinder
    lpoke partitionentry+8,startsector           ; StartSector   db 080h,000h,000h,000h
    lpoke partitionentry+12,1024*KIBsize/_sectorsize - 6144  ; #sectors in partition  db 000h,0E8h,000h,000h

     hdoffset startsector*_sectorsize
 end if

 bootsector:
   file bootcode
       poke bootsector+003h, 'M'              ; oem/id name
       poke bootsector+004h, 'S'
       poke bootsector+005h, 'D'
       poke bootsector+006h, 'O'
       poke bootsector+007h, 'S'
       poke bootsector+008h, '5'
       poke bootsector+009h, '.'
       poke bootsector+00Ah, '0'
ssz:  dpoke bootsector+00Bh, _sectorsize      ; bytes per sector
       poke bootsector+00Dh, 001h             ; sectors per allocation
      dpoke bootsector+00Eh, _rssectorsbeforefat  ; reserved sectors before first FAT    fat1=bootsector+_rssectorsbeforefat*_sectorsize=010400h
       poke bootsector+010h, 002h             ; number of fileallocation tables
      dpoke bootsector+011h, _rootentries     ;0200h max of 32 byte root entries     ;_rootentries*32=16384 bytes
hds:  dpoke bootsector+013h, 1024*KIBsize/_sectorsize - 6144  ;(000h,0E8h) total sectors
       poke bootsector+015h, 0F8h             ; media, copied into first byte of FAT
spf:  dpoke bootsector+016h, _sectorsperfat   ;(fat2-fat1)/_sectorsize  ;(0E7h,000h) sectors per file allocation table fat2=fat1+_sectorsize*_sectorsperfat=02d200h
      dpoke bootsector+018h, 03Fh             ; sectors per track
      dpoke bootsector+01Ah, 010h             ; number of heads
      lpoke bootsector+01Ch, 080h             ; count of hidden sectors
      lpoke bootsector+020h, 000h             ; total sectors if greater than 65536
       poke bootsector+024h, 080h             ; physical drivenumber
       poke bootsector+025h, 000h             ; nt reserved
       poke bootsector+026h, 029h             ; extended boot signature
      lpoke bootsector+027h, 058EFA861h       ; volumen serial
       poke bootsector+02Bh, 'N'              ; volume name
       poke bootsector+02Ch, 'O'
       poke bootsector+02Dh, ' '
       poke bootsector+02Eh, 'N'
       poke bootsector+02Fh, 'A'
       poke bootsector+030h, 'M'
       poke bootsector+031h, 'E'
       poke bootsector+032h, ' '
       poke bootsector+033h, ' '
       poke bootsector+034h, ' '
       poke bootsector+035h, ' '
       poke bootsector+036h, 'F'              ; fat type
       poke bootsector+037h, 'A'
       poke bootsector+038h, 'T'
       poke bootsector+039h, '1'
       poke bootsector+03Ah, '6'
       poke bootsector+03Bh, ' '
       poke bootsector+03Ch, ' '
       poke bootsector+03Dh, ' '
      dpoke bootsector+510,0AA55h

 hdoffset bootsector+_rssectorsbeforefat*_sectorsize
 fat1:
       db 0F8h,0FFh   ;#0 we are a HD
       db 0FFh,0FFh   ;#1

 hdoffset fat1+_sectorsize*_sectorsperfat
 fat2:
       db 0F8h,0FFh   ;#0 we are a HD
       db 0FFh,0FFh   ;#1

 hdoffset fat2+_sectorsize*_sectorsperfat
 rootdirectory:
       db 'PHAT16-7   ',008h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0EEh,059h,028h,03Ch, 000h,000h, 000h,000h,000h,000h
       rootdirptr=$

 hdoffset rootdirectory+_rootentries*32
 dataclusters:
 cluster=2            ; skip reserved entries
}
macro padclusters
{
      freeclusters:
        rb 1024*KIBsize-($-zero)-2
        db 0,0
}


; eg. create a partitioned disc image 32MB, with mbr code, boot code, and flat file filesystem
; bootcode is read in at sector start, may be _sectorsize bytes
;            size in KiB

      DiscImage 32*1024,'mbr.bin','boot16b.bin'
;      DiscImage 32*1024,'','boot16b.bin'


      inject 'ARGTEST.APP' ,'A','R','G','T','E','S','T',' ','A','P','P' ;4E000
      inject 'ETHTOOL.APP' ,'E','T','H','T','O','O','L',' ','A','P','P' ;4E200
      inject 'hello.app'   ,'H','E','L','L','O',' ',' ',' ','A','P','P' ;4E400
      inject 'kernel64.sys','K','E','R','N','E','L','6','4','S','Y','S' ;4E600
      inject 'keyboard.app','K','E','Y','B','O','A','R','D','A','P','P' ;52600
      inject 'pure64.sys'  ,'P','U','R','E','6','4',' ',' ','S','Y','S' ;52800
      inject 'smptest.app' ,'S','M','P','T','E','S','T',' ','A','P','P' ;55000
      inject 'sysinfo.app' ,'S','Y','S','I','N','F','O',' ','A','P','P' ;55200
      inject 'primeasm.app','P','R','I','M','E','A','S','M','A','P','P' ;55600
      inject 'filetest.app','F','I','L','E','T','E','S','T','A','P','P' ;55800

      padclusters


    
Post 14 Apr 2011, 22:55
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Code:
macro store_uppercase char*{

  if char >= 'a' & char <= 'z'
    db (char) - 'a' + 'A'
  else
    db char
  end if
}

macro write_fat_name filename*{
local ..char, ..dotFound

  virtual at 0
    db filename

    if $ > 8 + 1 + 3
      err 'File name too large!'
    end if

    db 8 + 1 + 3 - $  dup(' ')

  rept 8 + 1 + 3 i:0\{
    load ..char\#i byte from i
  \}
  end virtual

  ..dotFound = 0

  rept 8 + 1 + 3 i:0\{
    if ..dotFound
      if ..char\#i = '.'
        err 'Extension specified more than once!'
      end if
      if i <= 8
        db ' '
      end if
    else if ..char\#i = '.'
      ..dotFound = i
    else
      store_uppercase ..char\#i
    end if
  \}

  if ..dotFound = 0 | ..dotFound > 8
    err 'Incorrect extension'
  end if

  rept 8 + 1 + 3 i:0\{
    if i > ..dotFound & i <= ..dotFound + 3
      store_uppercase ..char\#i
    end if
  \}
}

write_fat_name 'SysInfo.app' ; <- Example    
Post 15 Apr 2011, 06:05
View user's profile Send private message Reply with quote
egos



Joined: 10 Feb 2009
Posts: 144
egos
Code:
...fatname1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11    
Wow! You could use one argument like me:
Code:
macro dent id, name, attr
{
@@ db name
times @b+11-$ db 32
db attr
...
}

dent fileid,"FILE    TXT",FA_ARC
dent dirid,"DIR",FA_DIR
    
Post 15 Apr 2011, 07:59
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
New version using making less load to the preprocessor side (and saving compile-time memory)
Code:
macro store_uppercase char*{

  if char >= 'a' & char <= 'z'
    db (char) - 'a' + 'A'
  else
    db char
  end if
}

macro shift reg*, out*{
  out   = reg#0 and $FF

  reg#0 = reg#0 shr 8
  reg#0 = (reg#1 and $FF) shl 56 or reg#0

  reg#1 = reg#1 shr 8
}

macro write_fat_name filename*{
local ..r, ..char, ..i, ..j

  virtual at 0
    db filename

    if $ > 8 + 1 + 3
      err 'File name too large!'
    end if

    db 16 - $ dup(' ')

    load r0 qword from $$
    load r1 qword from $$+8
  end virtual

  shift r, ..char
  ..i = 0

  while ..i <= 8 & ..char <> '.'
    store_uppercase ..char
    shift r, ..char

    ..i = ..i + 1
  end while

  if ..char <> '.' | ..i > 8
    err 'Incorrect extension'
  end if

  db 8 - ..i dup(' ')

  ..j = 0
  repeat 8 + 1 + 3 - ..i
    shift r, ..char
    if ..char = '.'
      err 'Extension specified more than once!'
    end if

    if ..j = 3 & ..char <> ' '
      err 'Extension too large!'
    end if

    if ..j < 3
      store_uppercase ..char
      ..j = ..j + 1
    end if
  end repeat
}

write_fat_name 'SysInfo.app' ; <- Example    


The macro you have to use is write_fat_name. Note that although I placed some checks them are not enough so try to always provide valid file names Razz
Post 15 Apr 2011, 17:10
View user's profile Send private message Reply with quote
codelab



Joined: 03 Apr 2006
Posts: 16
Location: Denmark
codelab
Thanks for your replies !!!
Quote:

Wow! You could use one argument like me:
- But i have to process a normal filename, initially Id like to get the string length of say 'test.bin' without having this stored in a db sequence, but only in variables.
so 'test.bin' IN and 'test bin' OUT and no memory affected

Loco's is processing this correct but also stores in memory. and maybe this is the only way ? but sample will work for the root entry purpose.

sort of temp buffer / macro parameter properties, not affecting the binary....
Post 15 Apr 2011, 22:07
View user's profile Send private message Reply with quote
egos



Joined: 10 Feb 2009
Posts: 144
egos
You could make something like this:
Code:
repeat 11
virtual at 0
db name
times 11-$ db 32 
load sym from %-1
end virtual
store sym at rootdirptr+%-1
end repeat
    
Post 16 Apr 2011, 06:11
View user's profile Send private message Reply with quote
codelab



Joined: 03 Apr 2006
Posts: 16
Location: Denmark
codelab
Here's a dirty sample explaining a bit better

Code:
macro addfile filename
{
 local  fname
 align  buffer11b+512                  ; here is a heading buffer for temp use
 fname:
        write_fat_name filename
        bmov fname,tableptr            ; add entry
        file filename                  ; Actual file insert here, with odd alignment
        tableptr=tableptr+32
}
table:
        rb 32*no_of_root_entries
fileclusters:
tableptr=table
addfile 'test.bin'
addfile 'test2.bin'
relocate_files_and_discard_buffers      ; now all heading buffers are overwritten and we are aligned to 512
                                        ; but we have used memory in the binary for storage
                                        ; this is not a happy solution, since we might want
                                        ; to assemble directly instead of include binary file
                                        ; which requiring more complex relocation
    
Post 16 Apr 2011, 09:36
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.