flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Minimal FAT12 Header

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
rhyno_dagreat



Joined: 31 Jul 2006
Posts: 487
Location: Maryland, Unol Daleithiau
rhyno_dagreat
I found this old code of mine, got it working today and decided it may be beneficial to this forum (especially people new to OS programming). Enjoy!

Code:
;MINIMAL FAT12 BOOTABLE DISK!
;By: Rhyno_DaGreat (Ryan Lloyd)
;Description: A tutorial on how to hardcode a FAT12 Header for a bootdisk.

ORG 7C00h ;Add offsets of the segments to this automatically - This offset will render the disk bootable.

jmp start ;First two bytes - jump to start
nop ;Null byte - Needed to make 3 bytes at the beginning total

db "RhYn0v01" ;OEM Name
dw 512 ;Bytes Per Sector
db 1 ;Sectors Per Cluster
dw 1 ;Reserved Sector Count - 1 For BootSector
db 2 ;Number of File Allocation Tables
dw 160 ;Max number of Root Entries (16 * 10)
dw 80 * 2 * 18 ;Total Sectors
db 0xF0 ;Media Descriptor
dw 10 ;Sectors Per FAT
dw 18 ;Sectors Per Track
dw 2 ;Number of Heads
dd 0 ;Number of Hidden Sectors

start: ;Start it up!

times 510-($-$$) db 0 ;Fill in rest of bootsector with zeros
dw 0xAA55 ;Except last WORD, which is the boot signature Wink

fat1: ;Hardcoding the first File Allocation Table
db 0xF0, 0xFF, 0xFF ;First byte is same as Media Descriptor Byte, all other bits are set to one in (For the first cluster)
times 5120-($-fat1) db 0 ;FAT is 5120 bytes big (Sectors Per FAT * Size Of Sector [512 Bytes])

fat2: ;Backup copy of FAT
db 0xF0, 0xFF, 0xFF
times 5120-($-fat2) db 0

root_dir: ;Begining of Root Directory
        ;db "KERNEL  ", "COM", 0x04, 0, 0
        ;dw 0x0, 0x0, 0x0, 0x0, 0x0, 0x0; UNFINISHED, see Wikipedia FAT under "Directory Table"
times 5120-($-root_dir) db 0 ;Root Directory is 5120 bytes big also

;times 1456128-($-$$) db 0 ;Size of a floppy
    


Hope this helps explain the structure of the FAT to some of you.

Remember, it's in the following format from left to right:

[BootSector][File Allocation Table 1][File Allocation Table 2][Root Directory][Disk Space]
Post 16 Nov 2007, 17:49
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4240
Location: 2018
edfed
fine
i don't understand why we need to be in 2007 to have access to good resources
Post 16 Nov 2007, 17:59
View user's profile Send private message Visit poster's website Reply with quote
rhyno_dagreat



Joined: 31 Jul 2006
Posts: 487
Location: Maryland, Unol Daleithiau
rhyno_dagreat
Lol, the code is only 6 months old tops. I took a break after I couldn't get it working (in other words, readable by Windows). Then today I realized that the jump wasn't automatically 3 bytes big, but rather a near jump, so I included the "nop" and got it working. =D
Post 16 Nov 2007, 18:28
View user's profile Send private message Reply with quote
rhyno_dagreat



Joined: 31 Jul 2006
Posts: 487
Location: Maryland, Unol Daleithiau
rhyno_dagreat
Oh, don't try running it. Rather, use RawWrite or the program of your choice to copy it to a floppy and open it in Windows or DOS (or another OS that supports FAT12).
Post 16 Nov 2007, 18:32
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4240
Location: 2018
edfed
is the fat 12 free? or a copyrighted owned by ms file system?
with royalties
Post 16 Nov 2007, 19:20
View user's profile Send private message Visit poster's website Reply with quote
rhyno_dagreat



Joined: 31 Jul 2006
Posts: 487
Location: Maryland, Unol Daleithiau
rhyno_dagreat
Owned by MS with Royalties. For every unit sold you have to pay them 25 cents.
Post 17 Nov 2007, 02:08
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4240
Location: 2018
edfed
ok
so, i will use fat12 for the begining of the devellopment
after i will use an alternate fs for all.
a fs without any royalties for anybody
a GPL like licensed file system

or i will not sold the os
then they cannot force me to pay these shitty 25 cents/license
FUCK OFF!
Post 17 Nov 2007, 12:27
View user's profile Send private message Visit poster's website Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
rhyno_dagreat wrote:
Owned by MS with Royalties. For every unit sold you have to pay them 25 cents.

Fat12 is out of copyright, same as fat16, but its the LFN that is still under copyright.
So you are free to use fat12/16 without LFN.
Quote from the wiki
Quote:

On 2003-12-03 Microsoft announced it would be offering licenses for use of its FAT specification and "associated intellectual property", at the cost of a US$0.25 royalty per unit sold, with a $250,000 maximum royalty per license agreement.[21]



To this end, Microsoft cited four patents on the FAT file system as the basis of its intellectual property claims. All four pertain to long-filename extensions to FAT first seen in Windows 95:
Post 17 Nov 2007, 13:31
View user's profile Send private message Reply with quote
bogdanontanu



Joined: 07 Jan 2004
Posts: 403
Location: Sol. Earth. Europe. Romania. Bucuresti
bogdanontanu
AFAIK everybody that ever released any FAT12/16/32 commercial device (with or without LFN) did payed the 0.25 to Microsoft.

If you want commercial success it does not make a good start to deny the copyright rights of others... maybe you will be stolen also when you have something "good to sell".

But IF you do not want success then I guess Microsoft will not come after you... (although legally they can even if you gain no money)

Just do not live in illusions.

Hence I do suggest that you do not base your OS on FAT or be prepared to pay your respects. In fact IF you are prepared to pay then I see no reasome why you should not used FAT filesystem.

Otherwise, you can use FAT as a compatibility or fair use to exchange documents... but IF your OS boots from FAT or it is based in operation on FAT (reads ini or registry or loads drives at startup etc) then you have a problem IMHO.

Do not forget that Microsoft did invented this FATxx filesystem format not you. Hence "out of copyright" is kind of impossible.

Patents is something else but the laws and regulations depend on each country on patents issues.
Post 17 Nov 2007, 14:11
View user's profile Send private message Visit poster's website Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
bogdanontanu wrote:
AFAIK everybody that ever released any FAT12/16/32 commercial device (with or without LFN) did payed the 0.25 to Microsoft.

If you want commercial success it does not make a good start to deny the copyright rights of others... maybe you will be stolen also when you have something "good to sell".

But IF you do not want success then I guess Microsoft will not come after you... (although legally they can even if you gain no money)

Just do not live in illusions.

Hence I do suggest that you do not base your OS on FAT or be prepared to pay your respects. In fact IF you are prepared to pay then I see no reasome why you should not used FAT filesystem.

Otherwise, you can use FAT as a compatibility or fair use to exchange documents... but IF your OS boots from FAT or it is based in operation on FAT (reads ini or registry or loads drives at startup etc) then you have a problem IMHO.

Do not forget that Microsoft did invented this FATxx filesystem format not you. Hence "out of copyright" is kind of impossible.

Patents is something else but the laws and regulations depend on each country on patents issues.


What a load of rubbish, if its does not use LFN then you do not need to pay, what "commercial device" have you see released, that does not use LFN in the last 5 year's ?.
As they all use LFN, that why they need to pay.

I beleave in paying your jew, but when the patent runs out, that's it.
If not the world owe the UK alot of money, eg:
Quote:

Over the past 50 years, according to Japanese research, more than 40 per cent of discoveries taken up on a worldwide basis originated in the United Kingdom.
Post 17 Nov 2007, 16:34
View user's profile Send private message Reply with quote
bogdanontanu



Joined: 07 Jan 2004
Posts: 403
Location: Sol. Earth. Europe. Romania. Bucuresti
bogdanontanu
Quote:

What a load of rubbish ...

Well, that is simply my own opinion... I do not intend to convince anybody and I do not even claim it to be true. Everybody can use his own mind.

Devices are under NDA.
Post 17 Nov 2007, 17:16
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 2914
Location: [RSP+8*5]
bitRAKE
FAT, smat - any person could devise a better file system than FAT. Rolling Eyes

If your building an OS then what do you care about existing tools that use FAT? Just document whatever scheme you are using and it's limitations. Make the disk one big flat file that gets completely loaded into memory - some Atari/Amiga games did just that (there was no file system). Track which sectors get 'dirty' and write them back on shutdown. Very Happy

Where has the creativity in the world gone?
Post 17 Nov 2007, 19:16
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4240
Location: 2018
edfed
not simply a flat file
providing the variable-size, multi-file structure, you permit sharing and easy evolutivity of all the system.

the best is to make a file system that appears in HD exacttly as it must be in RAM and seek into RAM the file we need, if not in RAM, seek on Drive.
Drive is then LBA mapped, LBA limit is the segment limit
Pages are then clusters of the drive
Clusters are pages on RAM
Page translation relocate the cluster on an allocated memory segment

is partition really important
for exemple, i never use partition, i always use integral drives,
C: on IDE1 as master contain primary system & data
bios 81h on IDE1 as slave contain my system & data
D: on IDE2 as master contain data
E: on IDE2 as slave DVD ROM

if i need a safe disk space on my system drive, i will "simply" make some hidden roots that are impossible to modify and relocate.using the IOpl rings...
physically located close to the center of the plates.less frequentlly accessed, slower data transfert, secure place ( heads scratchs )

this kind of design doesn't have any signification for Flash (ROM & Drives)
Post 19 Nov 2007, 14:21
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 764
Location: Massachusetts, USA
bitshifter
Has anyone written a NON-FAT bootloader?

If so, then i would like to see it!
Post 07 Dec 2007, 07:20
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4240
Location: 2018
edfed
wait please, my brain is planing on a very strange file system s.ince two years.

also, i've made a chaining .com loader.
the .com file is 64kb maximum.
.com can therefore handle wich file system you want ( can ).
Post 07 Dec 2007, 07:25
View user's profile Send private message Visit poster's website Reply with quote
bogdanontanu



Joined: 07 Jan 2004
Posts: 403
Location: Sol. Earth. Europe. Romania. Bucuresti
bogdanontanu
Quote:

Has anyone written a NON-FAT bootloader?

Yes, of course. For example Solar OS does not boot from a fat partition, instead it uses a proprietary format for booting from floppy or for booting from HDD / CD-ROM.

I think that XP does boot from a NTFS partition Razz (non fat again). AFAIK Linux can boot from a non fat partition also.

Quote:

If so, then i would like to see it!


Unfortunately Solar OS is no longer open source.

However to do such an "non fat" boot loader is very simple ... anybody should be able to do this by himself. Many sources are available on internet for such issues / boot loaders.
Post 07 Dec 2007, 07:48
View user's profile Send private message Visit poster's website Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u
Sure v2_os user its own file sys
v2_os boot loader
Code:
; 1. Setup stack and datasegment
; 2. Check for a 32 bit CPU
; 3. Get info from the booted drive
; 4. Check on which CHS the bootsector is
; 5. Load all System sectors
; 6. Set the correct values
; 7. jump to System
; changed by LTH, EKS, VP

; CHS positions and disk numbers are usually stored in cx and dx:
;   ch = cylinder
;   cl = sector and high cylinder
;   dh = head
;   dl = disk
;07/07/2000: bl=Boot Partition number [ML]

bits 16
org 7C00h

        jmp Begin

        FILLBYTES          align 8, db 255
        SIGNATURE          db '+V2_FS+', 0       ; 8
        FS_VERSION         db '001.001', 0       ; 16
        MAXOBJECTS         dd 128                ; 24
        CUROBJECTS         dd 0                  ; 28
        MAXSECTORS         dd 000000B40H         ; 32   0b40h-for fd, was a 011223344H
        FIRST_AVAILABLE    dd 16                 ; 36
        SECTORS4SYSTEM16   db 0                  ; 40
        SECTORS4SYSTEM32   db 0                  ; 41
        FIRSTDATASECTOR    dd 0                  ; 42

        V2OS            db 13, 10, 'V2-OS', 0
        LOADOK          db 'Ok', 13, 10, 0
        WrongCPUMsg     db '32 bit processor required.', 0
        BadPartTableMsg db 13, 10, 'Could not find the boot partition', 0
        ErrorMsg        db 13, 10
                        db 13, 10, 'di=', 0
                        db 13, 10, 'si=', 0
                        db 13, 10, 'bp=', 0
                        db 13, 10, 'sp=', 0
                        db 13, 10, 'bx=', 0
                        db 13, 10, 'dx=', 0
                        db 13, 10, 'cx=', 0
                        db 13, 10, 'ax=', 0
        HexDigits       db '0123456789ABCDEF'

        MAXSECTOR       db 0
        MAXHEAD         db 0


;----------------------------------------------------------------------------
; In:  cx, dh = CHS
; Out: cx, dh = new CHS
; Corrupted: al

IncreaseCHS:
        mov al, cl                      ; DL contains the high cylinder
        and cl, 00111111b               ; Kill the high cylinder stuff
        and al, 11000000b               ; Kill the sector stuff

        inc cl                          ; Increase the sector

        cmp cl, [MAXSECTOR]             ; Check Sector
        jna SectorStillOK

        mov cl, 1                       ; Sector=1, increase head (sectors start at 1, not at zero!)
        inc dh

        cmp dh, [MAXHEAD]
        jna HeadStillOK

        mov dh, 0                       ; Head=0, increase cylinder (heads start at 0)
        inc ch
        jno NoCylinderOverflow

        add al, 01000000b               ; increase high cylinder

NoCylinderOverflow:
HeadStillOK:
SectorStillOK:
        or  cl, al                      ; Merge the high-cylinder and the sector
        ret

;----------------------------------------------------------------------------
; In:  es:di = Buffer
;         si = Nr of sectors to read
;      cx,dx = CHS and disk of the first sector
; Out: es:di = end of the data in the buffer
;      cx,dx = CHS and disk of the next sector
; Corrupted: ax, bx, si, bp

ReadSectors:
        mov bp, 10
        jmp short ReadLoop

RetryRead:
        dec bp
        jz Error
        mov ah, 0               ; Reset drive
        int 13h
        jc Error
ReadLoop:
        mov bx, di
        mov ax, 0201h           ; Read sectors
        int 13h
        jc RetryRead

        mov ax, 0e2eh           ; Print a dot
        xor bx, bx
        int 10h

        call IncreaseCHS

        add di, 512             ; Get next sector

        dec si
        jnz ReadLoop
        ret

;----------------------------------------------------------------------------
; In: cl = byte to display
; Corrupted: ax, bx, di, bp

WriteHexByte:
        mov ah, 0eh                     ; Teletype output
        xor bx, bx                      ; Page 0, color 0

        shld di, cx, 12                 ; load high nibble into di
        and di, 15
        mov al, [HexDigits + di]        ; al = hex digit corresponding to di
        int 10h                         ; write it

        mov di, cx                      ; same procedure with the low nibble
        and di, 15
        mov al, [HexDigits + di]
        int 10h

        ret

;----------------------------------------------------------------------------
; In:  ds:si = Zero terminated message
; Out: ds:si = next message (if starting after the displayed message)
; Corrupted: ax, bx, bp

WriteMsg:
        mov ah, 0Eh             ; Teletype output
        xor bx, bx              ; Page 0, color 0
        jmp short StartLoop
NextLetter:
        int 10h                 ; 2nd, print it
StartLoop:
        lodsb                   ; 1st, load next letter
        or al, al
        jnz NextLetter
        ret

;----------------------------------------------------------------------------
; In: ah = error code

Error:
        pusha
        mov si, ErrorMsg
        mov dl, 8
.loop   call WriteMsg
        pop cx
        xchg cl, ch
        call WriteHexByte
        xchg cl, ch
        call WriteHexByte
        dec dl
        jnz .loop
        jmp short $

;----------------------------------------------------------------------------
; In: dl = bootdisk
; Out:

Begin:
        cli                     ; Dont interrupt this

        xor ax,ax
        mov ds,ax               ; Set the data segment to 0, (we use an offset of 7C00h)
        mov ss,ax               ; StackSegment is zero too
        mov sp, 7C00h           ; Stack grows downwards

; A small CPU check to determine if we run on a 386
; see http://www.ddj.com/articles/1996/9611/9611n/9611n.htm for details
        push sp
        pop ax
        cmp ax, sp
        je AtLeast286
WrongCPU:
        mov si, WrongCPUMsg
        call WriteMsg
        jmp short $
AtLeast286:
        mov word [18h], WrongCPU       ; install an exception handler
        mov [1ah], cs
        cwde                            ; and try out a 32 bit instruction

        push dx                 ; Save bootdisk
        mov ah,8                ; and get some information about it
        int 13h
        jc Error

        and cl, 00111111b       ; we don't check cylinders
        mov [MAXSECTOR], cl
        mov [MAXHEAD], dh

        mov ah,0                ; Reset the bootdrive
        pop dx
        int 13h
        jc Error

        mov si, V2OS
        call WriteMsg

        mov ax, 60h             ; The segment is used as disk buffer
        mov es, ax

; We don't know where System is at this point, so we have to find it out.
; If we have booted from floppy, it will be at 0:0:2 (chs) right after the
; bootsector. If we booted from HD, we must get the CHS from the partition
; table, In order to get the partition of which we have booted, we must look
; for an active V2OS-parition (ID=33h).
; BTW: the partition ID 33h is reserved. It's very likely that one of
; future FAT file systems will use it.

        mov cx, 1                       ; cx and dx point to the first sector
        mov dh, 0                       ; on the boot disk
        or dl, dl
        jns LoadSystem                  ; Since floppies are not partitioned,
                                        ; we can directly read System if we
                                        ; boot from a floppy.

; Booted from HD
; We need to load the partitiontable by loading the MBR into memory

        xor di, di              ; The MBR will be overwritten later
        mov si, cx
        call ReadSectors

        mov si, 512-2-64        ; Point to the partitiontable
        mov cx, 4

FindBootPartition:
        test byte [es:si], 80h          ; Check if this partition is active
        jz FindNext
        cmp byte [es:si + 4], 33h       ; Check if it got the correct ID
        je FoundThePartition
FindNext:
        add si,16                       ; Point to the next partition entry
        loop FindBootPartition

        mov si, BadPartTableMsg
        call WriteMsg
        jmp short $

FoundThePartition
        mov bx,5        ;[ML]
        sub bl, cl      ; partition number

        mov cx, [es:si + 2]             ; Get CHS from the partition table
        mov dh, [es:si + 1]

LoadSystem:
; cx and dx are set properly. Save this info before loading System
        push bx ;[ML]
        push cx                 ; Save sector, head, cylinder and disk
        push dx                 ; of the bootsector

        call IncreaseCHS        ; skip the bootsector

        xor di, di              ; Load System at 0600h (es is still 60h)
        movzx si, [SECTORS4SYSTEM16]
        call ReadSectors

        mov si, LOADOK
        call WriteMsg

; This info is needed before jumping to System.
        pop  dx                 ; Retrieve stack-saved cylinder, head, sector
        pop  cx                 ; and disk
        pop  bx                 ; and partition[ML]

; System prefers cl=cylinder and ch=sector, switch them before entering System
;        xchg cl,ch

        jmp 0050h:0100h


; Pad this bootsector out to 512 bytes. Generates a compiler error if the bootsector >512b
;LTH - if ya want to see the size of the code then comment out
;the next line (the times line)
        times 512-2-($-$$) db 90h
        dw 0AA55h                       ; Write boot signature
    

Note: Not coded with fasm
Post 08 Dec 2007, 00:04
View user's profile Send private message Reply with quote
rhyno_dagreat



Joined: 31 Jul 2006
Posts: 487
Location: Maryland, Unol Daleithiau
rhyno_dagreat
Here's an update on the code, which hard-codes a file called "HLOWRLD.TXT" in. The only problem I find is I know that the starting cluster for the file is put inside the root directory entry, but I can't understand the formatting of the FAT entries. Are they supposed to be 12-bits each? And if so, how are they set up?

Hope what I have here at least helps you!

Code:
;MINIMAL FAT12 BOOTABLE DISK!
;By: Rhyno_DaGreat (Ryan Lloyd)
;Description: A tutorial on how to hardcode a FAT12 Header for a bootdisk.

ORG 7C00h ;Add offsets of the segments to this automatically - This offset will render the disk bootable.

jmp start ;First two bytes - jump to start
nop ;Null byte - Needed to make 3 bytes at the beginning total

db "RhYn0v01" ;OEM Name
dw 512 ;Bytes Per Sector
db 1 ;Sectors Per Cluster
dw 1 ;Reserved Sector Count - 1 For BootSector
db 2 ;Number of File Allocation Tables
dw 160 ;Max number of Root Entries (16 * 10)
dw 80 * 2 * 18 ;Total Sectors
db 0xF0 ;Media Descriptor
dw 10 ;Sectors Per FAT
dw 18 ;Sectors Per Track
dw 2 ;Number of Heads
dd 0 ;Number of Hidden Sectors

start: ;Start it up!

times 510-($-$$) db 0 ;Fill in rest of bootsector with zeros
dw 0xAA55 ;Except last WORD, which is the boot signature Wink

fat1: ;Hardcoding the first File Allocation Table
db 0xF0, 0xFF, 0xFF, 0xFF, 0x0F ;First byte is same as Media Descriptor Byte, all other bits are set to one in (For the first cluster)
times 5120-($-fat1) db 0 ;FAT is 5120 bytes big (Sectors Per FAT * Size Of Sector [512 Bytes])

fat2: ;Backup copy of FAT
db 0xF0, 0xFF, 0xFF, 0xFF, 0x0F
times 5120-($-fat2) db 0

root_dir: ;Begining of Root Directory
       db "HLOWRLD ", "TXT", 0x20, 0x00, 0x00 ; Hardcode HLOWRLD.TXT file
       dw 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002
       dd 0x0000000B
times 5120-($-root_dir) db 0 ;Root Directory is 5120 bytes big also
; Hello World File:
db "Hello, World!"
;times 1456128-($-$$) db 0 ;Size of a floppy     
    
Post 08 Dec 2007, 18:42
View user's profile Send private message Reply with quote
Hayden



Joined: 06 Oct 2005
Posts: 132
Hayden
footnote.

We are allowed to create drivers, utils etc... for FAT sile systems. That is stuff like an optimized driver, a FAT file recovery program or some other utility. But we are not allowed to use the MS FAT technology for our own operateing systems, bootdisks etc... unless we have written permission, that usualy means an agreement must be met between you and MS.

here is the FAT specs...


Description:
Download
Filename: fatgen103.pdf
Filesize: 164.57 KB
Downloaded: 99 Time(s)


_________________
New User.. Hayden McKay.
Post 08 Dec 2007, 23:02
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 2914
Location: [RSP+8*5]
bitRAKE
Seems like a good reason to develop a x86-centric file system - something that reduces to very few instructions: XLATB and a byte-FAT array every 256 sectors. Zero bytes chain forward to next byte-FAT. Probably a bad idea with drive caches and all.
Post 09 Dec 2007, 00:21
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< 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 YouTube, Twitter.

Website powered by rwasa.