Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 4287 → Rev 4286

/kernel/branches/Kolibri-acpi/readme-ext-loader.txt
File deleted
/kernel/branches/Kolibri-acpi/core/sys32.inc
660,6 → 660,10
call free_cd_channel
and [cd_status], 0
@@:
cmp [flp_status], esi
jnz @f
and [flp_status], 0
@@:
pop esi
cmp [bgrlockpid], esi
jnz @f
/kernel/branches/Kolibri-acpi/core/syscall.inc
7,6 → 7,20
 
$Revision$
 
; Old style system call converter
align 16
cross_order:
; load all registers in crossed order
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, edi
movzx edi, byte[esp+28 + 4]
sub edi, 53
call dword [servetable+edi*4]
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSENTER ENTRY ;;
95,7 → 109,25
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
servetable:
dd 0
dd 0
dd 0
dd 0
dd 0
dd file_system ; 58-Common file system interface
dd 0
dd 0
dd 0
dd 0
dd 0
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; NEW SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
servetable2:
 
dd syscall_draw_window ; 0-DrawWindow
104,7 → 136,7
dd sys_clock ; 3-GetTime
dd syscall_writetext ; 4-WriteText
dd delay_hs_unprotected ; 5-DelayHs
dd undefined_syscall ; 6-deprecated OpenRamdiskFile
dd syscall_openramdiskfile ; 6-OpenRamdiskFile
dd syscall_putimage ; 7-PutImage
dd syscall_button ; 8-DefineButton
dd sys_cpuusage ; 9-GetProcessInfo
156,7 → 188,7
dd sound_interface ; 55-Sound interface
dd undefined_syscall ; 56-reserved
dd sys_pcibios ; 57-PCI BIOS32
dd undefined_syscall ; 58-deprecated Common file system interface
dd cross_order ; 58-Common file system interface
dd undefined_syscall ; 59-reserved
dd sys_IPC ; 60-Inter Process Communication
dd sys_gs ; 61-Direct graphics access
/kernel/branches/Kolibri-acpi/blkdev/disk.inc
1213,40 → 1213,8
; ecx = partition number, esi+ebp = ASCIIZ name
fs_dyndisk:
dec ecx ; convert to zero-based partition index
pop edx edx edx ; edx = pointer to DISK, dword [esp] = NULL or edx
; If the driver does not support insert notifications and we are the only fs
; operation with this disk, ask the driver whether the media
; was inserted/removed/changed. Otherwise, assume that media status is valid.
test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION
jz .media_accurate
push ecx esi
mov esi, edx
cmp dword [esp+8], 0
jz .test_no_media
cmp [esi+DISK.MediaRefCount], 2
jnz .media_accurate_pop
lea edx, [esi+DISK.MediaInfo]
and [edx+DISKMEDIAINFO.Flags], 0
mov al, DISKFUNC.querymedia
stdcall disk_call_driver, edx
pop edx edx edx eax ; edx = pointer to DISK, eax = NULL or edx
test eax, eax
jz .media_accurate_pop
stdcall disk_media_dereference ; drop our reference so that disk_media_changed could close the media
stdcall disk_media_changed, esi, 0
and dword [esp+8], 0 ; no media
.test_no_media:
stdcall disk_media_changed, esi, 1 ; issue fake notification
; if querymedia() inside disk_media_changed returns error, the notification is ignored
cmp [esi+DISK.MediaInserted], 0
jz .media_accurate_pop
lock inc [esi+DISK.MediaRefCount]
mov dword [esp+8], esi
.media_accurate_pop:
mov edx, esi
pop esi ecx
.media_accurate:
pop eax
test eax, eax
jz .nomedia
.main:
cmp ecx, [edx+DISK.NumPartitions]
1284,6 → 1252,30
.nomedia:
test ecx, ecx
jnz .notfound
test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION
jz .deverror
; if the driver does not support insert notifications and we are the only fs
; operation with this disk, issue the fake insert notification; if media is
; still not inserted, 'disk_media_changed' will detect this and do nothing
lea ecx, [edx+DISK.MediaLock]
call mutex_lock
cmp [edx+DISK.MediaRefCount], 1
jnz .noluck
call mutex_unlock
push edx
stdcall disk_media_changed, edx, 1
pop edx
lea ecx, [edx+DISK.MediaLock]
call mutex_lock
cmp [edx+DISK.MediaInserted], 0
jz .noluck
lock inc [edx+DISK.MediaRefCount]
call mutex_unlock
xor ecx, ecx
jmp .main
.noluck:
call mutex_unlock
.deverror:
mov dword [esp+32], ERROR_DEVICE
mov esi, edx
call disk_dereference
/kernel/branches/Kolibri-acpi/blkdev/flp_drv.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20,7 → 20,8
; add edi,ecx
give_back_application_data_1:
mov esi, FDD_BUFF;FDD_DataBuffer ;0x40000
mov ecx, 128
xor ecx, ecx
mov cx, 128
cld
rep movsd
ret
31,7 → 32,8
; add esi,ecx
take_data_from_application_1:
mov edi, FDD_BUFF;FDD_DataBuffer ;0x40000
mov ecx, 128
xor ecx, ecx
mov cx, 128
cld
rep movsd
ret
120,7 → 122,6
;* AL - выводимый байт. *
;***********************************
FDCDataOutput:
; DEBUGF 1,'K : FDCDataOutput(%x)',al
; pusha
push eax ecx edx
mov AH, AL ;запомнить байт в AH
136,7 → 137,6
je @@OutByteToFDC
loop @@TestRS
; Ошибка тайм-аута
; DEBUGF 1,' timeout\n'
mov [FDC_Status], FDC_TimeOut
jmp @@End_5
; Вывести байт в порт данных
144,7 → 144,6
inc DX
mov AL, AH
out DX, AL
; DEBUGF 1,' ok\n'
@@End_5:
; popa
pop edx ecx eax
171,7 → 170,6
je @@GetByteFromFDC
loop @@TestRS_1
; Ошибка тайм-аута
; DEBUGF 1,'K : FDCDataInput: timeout\n'
mov [FDC_Status], FDC_TimeOut
jmp @@End_6
; Ввести байт из порта данных
178,7 → 176,6
@@GetByteFromFDC:
inc DX
in AL, DX
; DEBUGF 1,'K : FDCDataInput: %x\n',al
@@End_6:
pop DX
pop ECX
188,7 → 185,6
;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
;*********************************************
FDCInterrupt:
; dbgstr 'FDCInterrupt'
; Установить флаг прерывания
mov [FDD_IntFlag], 1
mov al, 1
211,12 → 207,12
jnz @@End_7 ;прерывание произошло
mov eax, [timer_ticks]
sub eax, [TickCounter]
cmp eax, 200;50 ;25 ;5 ;ожидать 5 тиков
cmp eax, 50 ;25 ;5 ;ожидать 5 тиков
jb @@TestRS_2
; jl @@TestRS_2
; Ошибка тайм-аута
; dbgstr 'WaitFDCInterrupt: timeout'
mov [FDC_Status], FDC_TimeOut
; mov [flp_status],0
@@End_7:
popa
ret
225,7 → 221,6
;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" *
;*********************************
FDDMotorON:
; dbgstr 'FDDMotorON'
pusha
; cmp [fdd_motor_status],1
; je fdd_motor_on
257,20 → 252,6
sub eax, [TickCounter]
cmp eax, 50 ;10
jb @@dT
; Read results of RESET command
push 4
; DEBUGF 1,'K : floppy reset results:'
@@:
mov al, 8
call FDCDataOutput
call FDCDataInput
; DEBUGF 1,' %x',al
call FDCDataInput
; DEBUGF 1,' %x',al
dec dword [esp]
jnz @b
; DEBUGF 1,'\n'
pop eax
cmp [flp_number], 1
jne fdd_motor_on_B
mov [fdd_motor_status], 1
294,6 → 275,8
;* ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА *
;*****************************************
proc check_fdd_motor_status_has_work?
cmp [flp_status], 0
jnz .yes
cmp [fdd_motor_status], 0
jz .no
mov eax, [timer_ticks]
320,6 → 303,7
call FDDMotorOFF
mov [fdd_motor_status], 0
end_check_fdd_motor_status_1:
mov [flp_status], 0
end_check_fdd_motor_status:
ret
 
327,7 → 311,6
;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА *
;**********************************
FDDMotorOFF:
; dbgstr 'FDDMotorOFF'
push AX
push DX
cmp [flp_number], 1
340,8 → 323,8
pop DX
pop AX
; сброс флагов кеширования в связи с устареванием информации
or [floppy_media_flags+0], FLOPPY_MEDIA_NEED_RESCAN
or [floppy_media_flags+1], FLOPPY_MEDIA_NEED_RESCAN
mov [root_read], 0
mov [flp_fat], 0
ret
 
FDDMotorOFF_A:
360,11 → 343,8
;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" *
;*******************************
RecalibrateFDD:
; dbgstr 'RecalibrateFDD'
pusha
call save_timer_fdd_motor
; Сбросить флаг прерывания
mov [FDD_IntFlag], 0
; Подать команду "Рекалибровка"
mov AL, 07h
call FDCDataOutput
372,18 → 352,10
call FDCDataOutput
; Ожидать завершения операции
call WaitFDCInterrupt
cmp [FDC_Status], 0
jne .fail
; Read results of RECALIBRATE command
; DEBUGF 1,'K : floppy recalibrate results:'
mov al, 8
call FDCDataOutput
call FDCDataInput
; DEBUGF 1,' %x',al
call FDCDataInput
; DEBUGF 1,' %x',al
; DEBUGF 1,'\n'
.fail:
; cmp [FDC_Status],0
; je no_fdc_status_error
; mov [flp_status],0
;no_fdc_status_error:
call save_timer_fdd_motor
popa
ret
396,7 → 368,6
;* Результат операции заносится в FDC_Status. *
;*****************************************************
SeekTrack:
; dbgstr 'SeekTrack'
pusha
call save_timer_fdd_motor
; Сбросить флаг прерывания
431,20 → 402,17
cmp AL, [FDD_Track]
jne @@Err
; Номер головки совпадает с заданным?
; The H bit (Head Address) in ST0 will always return a "0" (c) 82077AA datasheet,
; description of SEEK command. So we can not verify the proper head.
; mov AL, [FDC_ST0]
; and AL, 100b
; shr AL, 2
; cmp AL, [FDD_Head]
; jne @@Err
mov AL, [FDC_ST0]
and AL, 100b
shr AL, 2
cmp AL, [FDD_Head]
jne @@Err
; Операция завершена успешно
; dbgstr 'SeekTrack: FDC_Normal'
mov [FDC_Status], FDC_Normal
jmp @@Exit
@@Err: ; Трек не найден
; dbgstr 'SeekTrack: FDC_TrackNotFound'
mov [FDC_Status], FDC_TrackNotFound
; mov [flp_status],0
@@Exit:
call save_timer_fdd_motor
popa
461,7 → 429,6
;* содержимое сектора будет занесено в FDD_DataBuffer. *
;*******************************************************
ReadSector:
; dbgstr 'ReadSector'
pushad
call save_timer_fdd_motor
; Сбросить флаг прерывания
501,12 → 468,11
call GetStatusInfo
test [FDC_ST0], 11011000b
jnz @@Err_1
; dbgstr 'ReadSector: FDC_Normal'
mov [FDC_Status], FDC_Normal
jmp @@Exit_1
@@Err_1:
; dbgstr 'ReadSector: FDC_SectorNotFound'
mov [FDC_Status], FDC_SectorNotFound
; mov [flp_status],0
@@Exit_1:
call save_timer_fdd_motor
popad
545,10 → 511,12
inc [RecalRepCounter]
cmp [RecalRepCounter], 3
jb @@TryAgain
; mov [flp_status],0
@@Exit_2:
popa
ret
@@Err_3:
mov [flp_status], 0
popa
ret
 
563,7 → 531,6
;* содержимое FDD_DataBuffer будет занесено в сектор. *
;*******************************************************
WriteSector:
; dbgstr 'WriteSector'
pushad
call save_timer_fdd_motor
; Сбросить флаг прерывания
649,6 → 616,7
popa
ret
@@Err_4:
mov [flp_status], 0
popa
ret
 
674,276 → 642,3
pop AX
ret
 
; Interface for disk subsystem.
; Assume fixed capacity for 1.44M.
FLOPPY_CAPACITY = 2880 ; in sectors
 
iglobal
align 4
floppy_functions:
dd .size
dd 0 ; no close() function
dd 0 ; no closemedia() function
dd floppy_querymedia
dd floppy_read
dd floppy_write
dd 0 ; no flush() function
dd 0 ; no adjust_cache_size() function
.size = $ - floppy_functions
endg
 
uglobal
floppy_media_flags rb 2
n_sector dd 0 ; temporary save for sector value
flp_number db 0 ; 1- Floppy A, 2-Floppy B
old_track db 0 ; old value track
flp_label rb 15*2 ; Label and ID of inserted floppy disk
align 4
; Hardware does not allow to work with two floppies in parallel,
; so there is one mutex guarding access to any floppy.
floppy_mutex MUTEX
endg
; Meaning of bits in floppy_media_flags
FLOPPY_MEDIA_PRESENT = 1 ; media was present when last asked
FLOPPY_MEDIA_NEED_RESCAN = 2 ; media was possibly changed, need to rescan
FLOPPY_MEDIA_LABEL_CHANGED = 4 ; temporary state
 
iglobal
floppy1_name db 'fd',0
floppy2_name db 'fd2',0
endg
 
; This function is called in boot process.
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
proc floppy_init
mov ecx, floppy_mutex
call mutex_init
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
test byte [DRIVE_DATA], 0xF0
jz .no1
stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
.no1:
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
test byte [DRIVE_DATA], 0x0F
jz .no2
stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
.no2:
ret
endp
 
; Returns information about disk media.
; Floppy drives do not support insert notifications,
; DISK_NO_INSERT_NOTIFICATION is set,
; the disk subsystem calls this function before each filesystem operation.
; If the media has changed, return error for the first call as signal
; to finalize work with old media and the true geometry for the second call.
; Assume that media is (possibly) changed anytime when motor is off.
proc floppy_querymedia
virtual at esp+4
.userdata dd ?
.info dd ?
end virtual
; 1. Acquire the global lock.
mov ecx, floppy_mutex
call mutex_lock
mov edx, [.userdata] ; 1 for /fd, 2 for /fd2
; 2. If the media was reported and has been changed, forget it and report an error.
mov al, [floppy_media_flags+edx-1]
and al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
cmp al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
jnz .not_reported
.no_media:
mov [floppy_media_flags+edx-1], 0
.return_no_media:
mov ecx, floppy_mutex
call mutex_unlock
mov eax, DISK_STATUS_NO_MEDIA
retn 8
.not_reported:
; 3. If we are in the temporary state LABEL_CHANGED, this is the second call
; after intermediate DISK_STATUS_NO_MEDIA due to media change;
; clear the flag and return the current geometry without rereading the bootsector.
cmp [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
jz .report_geometry
; 4. Try to read the bootsector.
mov [flp_number], dl
mov [FDC_Status], 0
call floppy_read_bootsector
; 5. If reading bootsector failed, assume that media is not present.
mov edx, [.userdata]
cmp [FDC_Status], 0
jnz .no_media
; 6. Check whether the previous status is "present". If not, go to 10.
push esi edi
imul edi, edx, 15
add edi, flp_label-15
mov esi, FDD_BUFF+39
mov ecx, 15
test [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
jz .set_label
; 7. Compare the old label with the current one.
rep cmpsb
; 8. If the label has not changed, go to 11.
jz .ok
; 9. If the label has changed, store it, enter temporary state LABEL_CHANGED
; and report DISK_STATUS_NO_MEDIA.
; dbgstr 'floppy label changed'
add esi, ecx
add edi, ecx
mov ecx, 15
sub esi, ecx
sub edi, ecx
rep movsb
mov [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
pop edi esi
jmp .return_no_media
.set_label:
; 10. The previous state was "not present". Copy the label.
rep movsb
.ok:
pop edi esi
.report_geometry:
; 11. Fill DISKMEDIAINFO structure.
mov ecx, [.info]
and [ecx+DISKMEDIAINFO.Flags], 0
mov [ecx+DISKMEDIAINFO.SectorSize], 512
mov dword [ecx+DISKMEDIAINFO.Capacity], FLOPPY_CAPACITY
and dword [ecx+DISKMEDIAINFO.Capacity+4], 0
; 12. Update state: media is present, data are actual.
mov [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
; 13. Release the global lock and return successful status.
mov ecx, floppy_mutex
call mutex_unlock
xor eax, eax
retn 8
endp
 
proc floppy_read_bootsector
pushad
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 0; Сторона
mov [FDD_Sector], 1; Сектор
call FDDMotorON
call RecalibrateFDD
cmp [FDC_Status], 0
jne .nothing
call SeekTrack
cmp [FDC_Status], 0
jne .nothing
call ReadSectWithRetr
.nothing:
popad
ret
endp
 
read_chs_sector:
call calculate_chs
call ReadSectWithRetr
ret
 
save_chs_sector:
call calculate_chs
call WriteSectWithRetr
ret
 
calculate_chs:
mov bl, [FDD_Track]
mov [old_track], bl
mov ebx, 18
xor edx, edx
div ebx
inc edx
mov [FDD_Sector], dl
mov edx, eax
shr eax, 1
and edx, 1
mov [FDD_Track], al
mov [FDD_Head], dl
mov dl, [old_track]
cmp dl, [FDD_Track]
je no_seek_track_1
call SeekTrack
no_seek_track_1:
ret
 
; Writes one or more sectors to the device.
proc floppy_write
mov dl, 1
jmp floppy_read_write
endp
 
; Reads one or more sectors from the device.
proc floppy_read
mov dl, 0
endp
 
; Common part of floppy_read and floppy_write.
proc floppy_read_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
virtual at ebp-8
.sectors_todo dd ?
.operation db ?
end virtual
push edx ; save operation code to [.operation]
; 1. Get number of sectors to read/write
; and zero number of sectors that were actually read/written.
mov eax, [numsectors_ptr]
push dword [eax] ; initialize [.sectors_todo]
and dword [eax], 0
push ebx esi edi ; save used registers to be stdcall
; 2. Acquire the global lock.
mov ecx, floppy_mutex
call mutex_lock
; 3. Set floppy number for this operation.
mov edx, [userdata]
mov [flp_number], dl
; 4. Read/write sector-by-sector.
.operation_loop:
; 4a. Check that the sector is inside the media.
cmp dword [start_sector+4], 0
jnz .end_of_media
mov eax, dword [start_sector]
cmp eax, FLOPPY_CAPACITY
jae .end_of_media
; 4b. For read operation, call read_chs_sector and then move data from FDD_BUFF to [buffer].
; For write operation, move data from [buffer] to FDD_BUFF and then call save_chs_sector.
cmp [.operation], 0
jz .read
mov esi, [buffer]
mov edi, FDD_BUFF
mov ecx, 512/4
rep movsd
mov [buffer], esi
call save_chs_sector
jmp @f
.read:
call read_chs_sector
mov esi, FDD_BUFF
mov edi, [buffer]
mov ecx, 512/4
rep movsd
mov [buffer], edi
@@:
; 4c. If there was an error, propagate it to the caller.
cmp [FDC_Status], 0
jnz .fail
; 4d. Otherwise, increment number of sectors processed and continue the loop.
mov eax, [numsectors_ptr]
inc dword [eax]
inc dword [start_sector]
dec [.sectors_todo]
jnz .operation_loop
; 5. Release the global lock and return with the correct status.
push 0
.return:
mov ecx, floppy_mutex
call mutex_unlock
pop eax
pop edi esi ebx ; restore used registers to be stdcall
ret ; this translates to leave/retn N and purges local variables
.fail:
push -1
jmp .return
.end_of_media:
push DISK_STATUS_END_OF_MEDIA
jmp .return
endp
/kernel/branches/Kolibri-acpi/blkdev/fdc.inc
21,48 → 21,40
ret
 
save_image:
cmp [ramdisk_actual_size], FLOPPY_CAPACITY
jnz .fail
call reserve_flp
call restorefatchain
pusha
mov ecx, floppy_mutex
call mutex_lock
mov [flp_number], bl
call floppy_read_bootsector
call check_label
cmp [FDC_Status], 0
jne .unnecessary_save_image
jne unnecessary_save_image
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 0; Сторона
mov [FDD_Sector], 1; Сектор
mov esi, RAMDISK
call SeekTrack
.save_image_1:
save_image_1:
push esi
call take_data_from_application_1
pop esi
add esi, 512
call WriteSectWithRetr
; call WriteSector
cmp [FDC_Status], 0
jne .unnecessary_save_image
jne unnecessary_save_image
inc [FDD_Sector]
cmp [FDD_Sector], 19
jne .save_image_1
jne save_image_1
mov [FDD_Sector], 1
inc [FDD_Head]
cmp [FDD_Head], 2
jne .save_image_1
jne save_image_1
mov [FDD_Head], 0
inc [FDD_Track]
call SeekTrack
cmp [FDD_Track], 80
jne .save_image_1
.unnecessary_save_image:
cmp [FDC_Status], 0
pushf
mov ecx, floppy_mutex
call mutex_unlock
popf
jne save_image_1
unnecessary_save_image:
popa
jnz .fail
xor eax, eax
mov [flp_status], 0
ret
.fail:
movi eax, 1
ret
 
/kernel/branches/Kolibri-acpi/blkdev/hd_drv.inc
47,10 → 47,6
hd1_data HD_DATA ?, 0x10, 2
hd2_data HD_DATA ?, 0, 3
hd3_data HD_DATA ?, 0x10, 4
 
hd_address_table:
dd 0x1f0, 0x00, 0x1f0, 0x10
dd 0x170, 0x00, 0x170, 0x10
endg
 
uglobal
649,6 → 645,14
end if
ret
;-----------------------------------------------------------------------------
hd_lba_error:
if lang eq sp
DEBUGF 1,"K : FS - HD error en LBA\n"
else
DEBUGF 1,"K : FS - HD LBA error\n"
end if
jmp LBA_read_ret
;-----------------------------------------------------------------------------
align 4
wait_for_hd_idle:
push eax edx
/kernel/branches/Kolibri-acpi/blkdev/rd.inc
1,195 → 1,2296
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RAMDISK functions ;;
;; (C) 2004 Ville Turjanmaa, License: GPL ;;
;; Addings by M.Lisovin ;;
;; LFN support by diamond ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
iglobal
align 4
ramdisk_functions:
dd .size
dd 0 ; no close() function
dd 0 ; no closemedia() function
dd ramdisk_querymedia
dd ramdisk_read
dd ramdisk_write
dd 0 ; no flush() function
dd ramdisk_adjust_cache_size
.size = $ - ramdisk_functions
 
; calculate fat chain
 
calculatefatchain:
 
pushad
 
mov esi, RAMDISK+512
mov edi, RAMDISK_FAT
 
fcnew:
mov eax, dword [esi]
mov ebx, dword [esi+4]
mov ecx, dword [esi+8]
mov edx, ecx
shr edx, 4;8 ok
shr dx, 4;7 ok
xor ch, ch
shld ecx, ebx, 20;6 ok
shr cx, 4;5 ok
shld ebx, eax, 12
and ebx, 0x0fffffff;4 ok
shr bx, 4;3 ok
shl eax, 4
and eax, 0x0fffffff;2 ok
shr ax, 4;1 ok
mov dword [edi], eax
mov dword [edi+4], ebx
mov dword [edi+8], ecx
mov dword [edi+12], edx
add edi, 16
add esi, 12
 
cmp edi, RAMDISK_FAT+2856*2;2849 clusters
jnz fcnew
 
popad
ret
 
 
restorefatchain: ; restore fat chain
 
pushad
 
mov esi, RAMDISK_FAT
mov edi, RAMDISK+512
 
fcnew2:
mov eax, dword [esi]
mov ebx, dword [esi+4]
shl ax, 4
shl eax, 4
shl bx, 4
shr ebx, 4
shrd eax, ebx, 8
shr ebx, 8
mov dword [edi], eax
mov word [edi+4], bx
add edi, 6
add esi, 8
 
cmp edi, RAMDISK+512+4278;4274 bytes - all used FAT
jb fcnew2
 
mov esi, RAMDISK+512 ; duplicate fat chain
mov edi, RAMDISK+512+0x1200
mov ecx, 1069;4274/4
cld
rep movsd
 
popad
ret
 
 
ramdisk_free_space:
;---------------------------------------------
;
; returns free space in edi
; rewr.by Mihasik
;---------------------------------------------
 
push eax ebx ecx
 
mov edi, RAMDISK_FAT;start of FAT
xor ax, ax;Free cluster=0x0000 in FAT
xor ebx, ebx;counter
mov ecx, 2849;2849 clusters
cld
rdfs1:
repne scasw
jnz rdfs2 ;if last cluster not 0
inc ebx
test ecx, ecx
jnz rdfs1
rdfs2:
shl ebx, 9;free clusters*512
mov edi, ebx
 
pop ecx ebx eax
ret
 
 
expand_filename:
;---------------------------------------------
;
; exapand filename with '.' to 11 character
; eax - pointer to filename
;---------------------------------------------
 
push esi edi ebx
 
mov edi, esp ; check for '.' in the name
add edi, 12+8
 
mov esi, eax
 
mov eax, edi
mov [eax+0], dword ' '
mov [eax+4], dword ' '
mov [eax+8], dword ' '
 
flr1:
 
cmp [esi], byte '.'
jne flr2
mov edi, eax
add edi, 7
jmp flr3
 
flr2:
 
mov bl, [esi]
mov [edi], bl
 
flr3:
 
inc esi
inc edi
 
mov ebx, eax
add ebx, 11
 
cmp edi, ebx
jbe flr1
 
pop ebx edi esi
ret
 
fileread:
;----------------------------------------------------------------
;
; fileread - sys floppy
;
; eax points to filename 11 chars
; ebx first wanted block ; 1+ ; if 0 then set to 1
; ecx number of blocks to read ; 1+ ; if 0 then set to 1
; edx mem location to return data
; esi length of filename 12*X 0=root
;
; ret ebx = size or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
test ebx, ebx;if ebx=0 - set to 1
jnz frfl5
inc ebx
frfl5:
test ecx, ecx;if ecx=0 - set to 1
jnz frfl6
inc ecx
frfl6:
test esi, esi ; return ramdisk root
jnz fr_noroot ;if not root
cmp ebx, 14 ;14 clusters=root dir
ja oorr
cmp ecx, 14
ja oorr
jmp fr_do
oorr:
mov eax, 5 ;out of root range (fnf)
xor ebx, ebx
dec ebx ;0xffffffff
ret
 
fr_do: ;reading rootdir
mov edi, edx
dec ebx
push edx
mov edx, ecx
add edx, ebx
cmp edx, 15 ;ebx+ecx=14+1
pushf
jbe fr_do1
sub edx, 14
sub ecx, edx
fr_do1:
shl ebx, 9
mov esi, RAMDISK+512*19
add esi, ebx
shl ecx, 7
cld
rep movsd
popf
pop edx
jae fr_do2
xor eax, eax; ok read
xor ebx, ebx
ret
fr_do2: ;if last cluster
mov eax, 6;end of file
xor ebx, ebx
ret
 
fr_noroot:
 
sub esp, 32
call expand_filename
 
dec ebx
 
push eax
 
push eax ebx ecx edx esi edi
call rd_findfile
je fifound
add esp, 32+28 ;if file not found
ret
 
fifound:
 
mov ebx, [edi-11+28] ;file size
mov [esp+20], ebx
mov [esp+24], ebx
add edi, 0xf
movzx eax, word [edi]
mov edi, eax ;edi=cluster
 
frnew:
 
add eax, 31 ;bootsector+2*fat+filenames
shl eax, 9 ;*512
add eax, RAMDISK ;image base
mov ebx, [esp+8]
mov ecx, 512 ;[esp+4]
 
cmp [esp+16], dword 0 ; wanted cluster ?
jne frfl7
call memmove
add [esp+8], dword 512
dec dword [esp+12] ; last wanted cluster ?
je frnoread
jmp frfl8
frfl7:
dec dword [esp+16]
frfl8:
movzx eax, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT
mov edi, eax
cmp edi, 4095 ;eof - cluster
jz frnoread2
 
cmp [esp+24], dword 512 ;eof - size
jb frnoread
sub [esp+24], dword 512
 
jmp frnew
 
frnoread2:
 
cmp [esp+16], dword 0 ; eof without read ?
je frnoread
 
pop edi esi edx ecx
add esp, 4
pop ebx ; ebx <- eax : size of file
add esp, 36
mov eax, 6 ; end of file
ret
 
frnoread:
 
pop edi esi edx ecx
add esp, 4
pop ebx ; ebx <- eax : size of file
add esp, 36
xor eax, eax;read ok
ret
 
 
 
rd_findfile:
;by Mihasik
;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
 
mov edi, RAMDISK+512*18+512;Point at directory
cld
rd_newsearch:
mov esi, eax
mov ecx, 11
rep cmpsb
je rd_ff
add cl, 21
add edi, ecx
cmp edi, RAMDISK+512*33
jb rd_newsearch
mov eax, 5 ;if file not found - eax=5
xor ebx, ebx
dec ebx ;ebx=0xffffffff and zf=0
rd_ff:
ret
 
; \begin{diamond}
 
uni2ansi_str:
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
; in: esi->source, edi->buffer (may be esi=edi)
; destroys: eax,esi,edi
lodsw
test ax, ax
jz .done
cmp ax, 0x80
jb .ascii
cmp ax, 0x401
jz .yo1
cmp ax, 0x451
jz .yo2
cmp ax, 0x410
jb .unk
cmp ax, 0x440
jb .rus1
cmp ax, 0x450
jb .rus2
.unk:
mov al, '_'
jmp .doit
.yo1:
mov al, 0xF0 ; 'Ё'
jmp .doit
.yo2:
mov al, 0xF1 ; 'ё'
jmp .doit
.rus1:
; 0x410-0x43F -> 0x80-0xAF
add al, 0x70
jmp .doit
.rus2:
; 0x440-0x44F -> 0xE0-0xEF
add al, 0xA0
.ascii:
.doit:
stosb
jmp uni2ansi_str
.done:
mov byte [edi], 0
ret
 
ansi2uni_char:
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
mov ah, 0
; 0x00-0x7F - trivial map
cmp al, 0x80
jb .ret
; 0x80-0xAF -> 0x410-0x43F
cmp al, 0xB0
jae @f
add ax, 0x410-0x80
.ret:
ret
@@:
; 0xE0-0xEF -> 0x440-0x44F
cmp al, 0xE0
jb .unk
cmp al, 0xF0
jae @f
add ax, 0x440-0xE0
ret
; 0xF0 -> 0x401
; 0xF1 -> 0x451
@@:
cmp al, 0xF0 ; 'Ё'
jz .yo1
cmp al, 0xF1 ; 'ё'
jz .yo2
.unk:
mov al, '_' ; ah=0
ret
.yo1:
mov ax, 0x401
ret
.yo2:
mov ax, 0x451
ret
 
char_toupper:
; convert character to uppercase, using cp866 encoding
; in: al=symbol
; out: al=converted symbol
cmp al, 'a'
jb .ret
cmp al, 'z'
jbe .az
cmp al, 0xF1 ; 'ё'
jz .yo1
cmp al, 0xA0 ; 'а'
jb .ret
cmp al, 0xE0 ; 'р'
jb .rus1
cmp al, 0xEF ; 'я'
ja .ret
; 0xE0-0xEF -> 0x90-0x9F
sub al, 0xE0-0x90
.ret:
ret
.rus1:
; 0xA0-0xAF -> 0x80-0x8F
.az:
and al, not 0x20
ret
.yo1:
; 0xF1 -> 0xF0
dec ax
ret
 
fat_get_name:
; in: edi->FAT entry
; out: CF=1 - no valid entry
; else CF=0 and ebp->ASCIIZ-name
; (maximum length of filename is 255 (wide) symbols without trailing 0,
; but implementation requires buffer 261 words)
; destroys eax
cmp byte [edi], 0
jz .no
cmp byte [edi], 0xE5
jnz @f
.no:
stc
ret
@@:
cmp byte [edi+11], 0xF
jz .longname
test byte [edi+11], 8
jnz .no
push ecx
push edi ebp
test byte [ebp-4], 1
jnz .unicode_short
 
mov eax, [edi]
mov ecx, [edi+4]
mov [ebp], eax
mov [ebp+4], ecx
 
mov ecx, 8
@@:
cmp byte [ebp+ecx-1], ' '
loope @b
 
mov eax, [edi+8]
cmp al, ' '
je .done
shl eax, 8
mov al, '.'
 
lea ebp, [ebp+ecx+1]
mov [ebp], eax
mov ecx, 3
@@:
rol eax, 8
cmp al, ' '
jne .done
loop @b
dec ebp
.done:
and byte [ebp+ecx+1], 0 ; CF=0
pop ebp edi ecx
ret
.unicode_short:
mov ecx, 8
push ecx
@@:
mov al, [edi]
inc edi
call ansi2uni_char
mov [ebp], ax
inc ebp
inc ebp
loop @b
pop ecx
@@:
cmp word [ebp-2], ' '
jnz @f
dec ebp
dec ebp
loop @b
@@:
mov word [ebp], '.'
inc ebp
inc ebp
mov ecx, 3
push ecx
@@:
mov al, [edi]
inc edi
call ansi2uni_char
mov [ebp], ax
inc ebp
inc ebp
loop @b
pop ecx
@@:
cmp word [ebp-2], ' '
jnz @f
dec ebp
dec ebp
loop @b
dec ebp
dec ebp
@@:
and word [ebp], 0 ; CF=0
pop ebp edi ecx
ret
.longname:
; LFN
mov al, byte [edi]
and eax, 0x3F
dec eax
cmp al, 20
jae .no ; ignore invalid entries
mov word [ebp+260*2], 0 ; force null-terminating for orphans
imul eax, 13*2
add ebp, eax
test byte [edi], 0x40
jz @f
mov word [ebp+13*2], 0
@@:
push eax
; now copy name from edi to ebp ...
mov eax, [edi+1]
mov [ebp], eax ; symbols 1,2
mov eax, [edi+5]
mov [ebp+4], eax ; 3,4
mov eax, [edi+9]
mov [ebp+8], ax ; 5
mov eax, [edi+14]
mov [ebp+10], eax ; 6,7
mov eax, [edi+18]
mov [ebp+14], eax ; 8,9
mov eax, [edi+22]
mov [ebp+18], eax ; 10,11
mov eax, [edi+28]
mov [ebp+22], eax ; 12,13
; ... done
pop eax
sub ebp, eax
test eax, eax
jz @f
; if this is not first entry, more processing required
stc
ret
@@:
; if this is first entry:
test byte [ebp-4], 1
jnz .ret
; buffer at ebp contains UNICODE name, convert it to ANSI
push esi edi
mov esi, ebp
mov edi, ebp
call uni2ansi_str
pop edi esi
.ret:
clc
ret
 
fat_compare_name:
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
; in: esi->name, ebp->name
; out: if names match: ZF=1 and esi->next component of name
; else: ZF=0, esi is not changed
; destroys eax
push ebp esi
.loop:
mov al, [ebp]
inc ebp
call char_toupper
push eax
lodsb
call char_toupper
cmp al, [esp]
jnz .done
pop eax
test al, al
jnz .loop
dec esi
pop eax
pop ebp
xor eax, eax ; set ZF flag
ret
.done:
cmp al, '/'
jnz @f
cmp byte [esp], 0
jnz @f
mov [esp+4], esi
@@:
pop eax
pop esi ebp
ret
 
fat_time_to_bdfe:
; in: eax=FAT time
; out: eax=BDFE time
push ecx edx
mov ecx, eax
mov edx, eax
shr eax, 11
shl eax, 16 ; hours
and edx, 0x1F
add edx, edx
mov al, dl ; seconds
shr ecx, 5
and ecx, 0x3F
mov ah, cl ; minutes
pop edx ecx
ret
 
fat_date_to_bdfe:
push ecx edx
mov ecx, eax
mov edx, eax
shr eax, 9
add ax, 1980
shl eax, 16 ; year
and edx, 0x1F
mov al, dl ; day
shr ecx, 5
and ecx, 0xF
mov ah, cl ; month
pop edx ecx
ret
 
bdfe_to_fat_time:
push edx
mov edx, eax
shr eax, 16
and dh, 0x3F
shl eax, 6
or al, dh
shr dl, 1
and dl, 0x1F
shl eax, 5
or al, dl
pop edx
ret
 
bdfe_to_fat_date:
push edx
mov edx, eax
shr eax, 16
sub ax, 1980
and dh, 0xF
shl eax, 4
or al, dh
and dl, 0x1F
shl eax, 5
or al, dl
pop edx
ret
 
fat_entry_to_bdfe:
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
; destroys eax
mov eax, [ebp-4]
mov [esi+4], eax ; ASCII/UNICODE name
fat_entry_to_bdfe2:
movzx eax, byte [edi+11]
mov [esi], eax ; attributes
movzx eax, word [edi+14]
call fat_time_to_bdfe
mov [esi+8], eax ; creation time
movzx eax, word [edi+16]
call fat_date_to_bdfe
mov [esi+12], eax ; creation date
and dword [esi+16], 0 ; last access time is not supported on FAT
movzx eax, word [edi+18]
call fat_date_to_bdfe
mov [esi+20], eax ; last access date
movzx eax, word [edi+22]
call fat_time_to_bdfe
mov [esi+24], eax ; last write time
movzx eax, word [edi+24]
call fat_date_to_bdfe
mov [esi+28], eax ; last write date
mov eax, [edi+28]
mov [esi+32], eax ; file size (low dword)
xor eax, eax
mov [esi+36], eax ; file size (high dword)
test ebp, ebp
jz .ret
push ecx edi
lea edi, [esi+40]
mov esi, ebp
test byte [esi-4], 1
jz .ansi
mov ecx, 260/2
rep movsd
mov [edi-2], ax
@@:
mov esi, edi
pop edi ecx
.ret:
ret
.ansi:
mov ecx, 264/4
rep movsd
mov [edi-1], al
jmp @b
 
bdfe_to_fat_entry:
; convert BDFE at edx to FAT entry at edi
; destroys eax
; attributes byte
test byte [edi+11], 8 ; volume label?
jnz @f
mov al, [edx]
and al, 0x27
and byte [edi+11], 0x10
or byte [edi+11], al
@@:
mov eax, [edx+8]
call bdfe_to_fat_time
mov [edi+14], ax ; creation time
mov eax, [edx+12]
call bdfe_to_fat_date
mov [edi+16], ax ; creation date
mov eax, [edx+20]
call bdfe_to_fat_date
mov [edi+18], ax ; last access date
mov eax, [edx+24]
call bdfe_to_fat_time
mov [edi+22], ax ; last write time
mov eax, [edx+28]
call bdfe_to_fat_date
mov [edi+24], ax ; last write date
ret
 
ramdisk_root_first:
mov edi, RAMDISK+512*19
clc
ret
ramdisk_root_next:
add edi, 0x20
cmp edi, RAMDISK+512*33
cmc
ret
 
ramdisk_root_extend_dir:
stc
ret
 
uglobal
; this is for delete support
rd_prev_sector dd ?
rd_prev_prev_sector dd ?
endg
 
; See memmap.inc.
; Currently size of memory allocated for the ramdisk is fixed.
; This should be revisited when/if memory map would become more dynamic.
RAMDISK_CAPACITY = 2880 ; in sectors
ramdisk_notroot_next:
add edi, 0x20
test edi, 0x1FF
jz ramdisk_notroot_next_sector
ret ; CF=0
ramdisk_notroot_next_sector:
push ecx
mov ecx, [eax]
push [rd_prev_sector]
pop [rd_prev_prev_sector]
mov [rd_prev_sector], ecx
mov ecx, [ecx*2+RAMDISK_FAT]
and ecx, 0xFFF
cmp ecx, 2849
jae ramdisk_notroot_first.err2
mov [eax], ecx
pop ecx
ramdisk_notroot_first:
mov eax, [eax]
cmp eax, 2
jb .err
cmp eax, 2849
jae .err
shl eax, 9
lea edi, [eax+(31 shl 9)+RAMDISK]
clc
ret
.err2:
pop ecx
.err:
stc
ret
ramdisk_notroot_next_write:
test edi, 0x1FF
jz ramdisk_notroot_next_sector
ramdisk_root_next_write:
ret
 
ramdisk_notroot_extend_dir:
pusha
xor eax, eax
mov edi, RAMDISK_FAT
mov ecx, 2849
repnz scasw
jnz .notfound
mov word [edi-2], 0xFFF
sub edi, RAMDISK_FAT
shr edi, 1
dec edi
mov eax, [esp+28]
mov ecx, [eax]
mov [RAMDISK_FAT+ecx*2], di
mov [eax], edi
shl edi, 9
add edi, (31 shl 9)+RAMDISK
mov [esp], edi
xor eax, eax
mov ecx, 128
rep stosd
popa
clc
ret
.notfound:
popa
stc
ret
 
rd_find_lfn:
; in: esi+ebp -> name
; out: CF=1 - file not found
; else CF=0 and edi->direntry
push esi edi
push 0
push ramdisk_root_first
push ramdisk_root_next
.loop:
call fat_find_lfn
jc .notfound
cmp byte [esi], 0
jz .found
.continue:
test byte [edi+11], 10h
jz .notfound
movzx eax, word [edi+26]
mov [esp+8], eax
mov dword [esp+4], ramdisk_notroot_first
mov dword [esp], ramdisk_notroot_next
test eax, eax
jnz .loop
mov dword [esp+4], ramdisk_root_first
mov dword [esp], ramdisk_notroot_next
jmp .loop
.notfound:
add esp, 12
pop edi esi
stc
ret
.found:
test ebp, ebp
jz @f
mov esi, ebp
xor ebp, ebp
jmp .continue
@@:
mov eax, [esp+8]
add esp, 16 ; CF=0
pop esi
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskRead - LFN variant for reading sys floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskRead:
cmp byte [esi], 0
jnz @f
or ebx, -1
mov eax, 10 ; access denied
ret
@@:
push edi
call rd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, 5 ; file not found
ret
.found:
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
xor ebx, ebx
.reteof:
mov eax, 6 ; EOF
pop edi
ret
@@:
mov ebx, [ebx]
.l1:
push ecx edx
push 0
mov eax, [edi+28]
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
mov byte [esp], 6 ; EOF
@@:
movzx edi, word [edi+26] ; cluster
.new:
jecxz .done
test edi, edi
jz .eof
cmp edi, 0xFF8
jae .eof
lea eax, [edi+31] ; bootsector+2*fat+filenames
shl eax, 9 ; *512
add eax, RAMDISK ; image base
; now eax points to data of cluster
sub ebx, 512
jae .skip
lea eax, [eax+ebx+512]
neg ebx
push ecx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
mov ebx, edx
call memmove
add edx, ecx
sub [esp], ecx
pop ecx
xor ebx, ebx
.skip:
movzx edi, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT
jmp .new
.eof:
mov ebx, edx
pop eax edx ecx
sub ebx, edx
jmp .reteof
.done:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
;
; esi points to filename; only root is folder on ramdisk
; ebx pointer to structure 32-bit number = first wanted block
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = size or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskReadFolder:
push edi
cmp byte [esi], 0
jz .root
call rd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
.found:
test byte [edi+11], 0x10
jnz .found_dir
pop edi
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
.found_dir:
movzx eax, word [edi+26]
add eax, 31
push 0
jmp .doit
.root:
mov eax, 19
push 14
.doit:
push esi ecx ebp
sub esp, 262*2 ; reserve space for LFN
mov ebp, esp
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names
mov ebx, [ebx]
; init header
push eax ecx
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
mov byte [edx], 1 ; version
pop ecx eax
mov esi, edi ; esi points to block of data of folder entry (BDFE)
.main_loop:
mov edi, eax
shl edi, 9
add edi, RAMDISK
push eax
.l1:
call fat_get_name
jc .l2
cmp byte [edi+11], 0xF
jnz .do_bdfe
add edi, 0x20
test edi, 0x1FF
jnz .do_bdfe
pop eax
inc eax
dec byte [esp+262*2+16]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+RAMDISK_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+16], 0
@@:
mov edi, eax
shl edi, 9
add edi, RAMDISK
push eax
.do_bdfe:
inc dword [edx+8] ; new file found
dec ebx
jns .l2
dec ecx
js .l2
inc dword [edx+4] ; new file block copied
call fat_entry_to_bdfe
.l2:
add edi, 0x20
test edi, 0x1FF
jnz .l1
pop eax
inc eax
dec byte [esp+262*2+16]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+RAMDISK_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+16], 0
@@:
jmp .main_loop
.done:
add esp, 262*2+4
pop ebp
mov ebx, [edx+4]
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
pop ecx esi edi edi
ret
 
iglobal
align 4
ramdisk_actual_size dd RAMDISK_CAPACITY
label fat_legal_chars byte
; 0 = not allowed
; 1 = allowed only in long names
; 3 = allowed
times 32 db 0
; ! " # $ % & ' ( ) * + , - . /
db 1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
; 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
db 3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
; @ A B C D E F G H I J K L M N O
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
; P Q R S T U V W X Y Z [ \ ] ^ _
db 3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
; ` a b c d e f g h i j k l m n o
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
; p q r s t u v w x y z { | } ~
db 3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
endg
 
; This function is called early in boot process.
; It creates filesystem /rd/1 based on raw image data loaded by somebody before
; to memory named as RAMDISK with max size RAMDISK_CAPACITY, may be less.
proc ramdisk_init
iglobal
ramdisk_name db 'rd',0
endg
push ebx esi ; save used registers to be stdcall
; 1. Register the device and the (always inserted) media in the disk subsystem.
stdcall disk_add, ramdisk_functions, ramdisk_name, 0, 0
test eax, eax
jz .fail
mov ebx, eax
stdcall disk_media_changed, eax, 1
; 2. We don't know actual size of loaded image,
; so try to calculate it using partition structure,
; assuming that file systems fill the real size based on contents of the partition.
; 2a. Prepare for loop over partitions.
fat_name_is_legal:
; in: esi->(long) name
; out: CF set <=> legal
; destroys eax
push esi
xor eax, eax
@@:
lodsb
test al, al
jz .done
cmp al, 80h
jae .big
test [fat_legal_chars+eax], 1
jnz @b
.err:
pop esi
clc
ret
.big:
; 0x80-0xAF, 0xE0-0xEF
cmp al, 0xB0
jb @b
cmp al, 0xE0
jb .err
cmp al, 0xF0
jb @b
jmp .err
.done:
sub esi, [esp]
cmp esi, 257
pop esi
ret
 
fat_next_short_name:
; in: edi->8+3 name
; out: name corrected
; CF=1 <=> error
pushad
mov ecx, 8
mov al, '~'
std
push edi
add edi, 7
repnz scasb
pop edi
cld
jz .tilde
; tilde is not found, insert "~1" at end
add edi, 6
cmp word [edi], ' '
jnz .insert_tilde
@@:
dec edi
cmp byte [edi], ' '
jz @b
inc edi
.insert_tilde:
mov word [edi], '~1'
popad
clc
ret
.tilde:
push edi
add edi, 7
xor ecx, ecx
xor edx, edx
; 2b. Check that at least one partition was recognized.
cmp [ebx+DISK.NumPartitions], ecx
jz .fail
; 2c. Loop over partitions.
.partitions:
; For every partition, set edx to maximum between edx and end of partition.
mov esi, [ebx+DISK.Partitions]
mov esi, [esi+ecx*4]
mov eax, dword [esi+PARTITION.FirstSector]
add eax, dword [esi+PARTITION.Length]
cmp eax, edx
jb @f
mov edx, eax
@@:
; after tilde may be only digits and trailing spaces
cmp byte [edi], '~'
jz .break
cmp byte [edi], ' '
jz .space
cmp byte [edi], '9'
jnz .found
dec edi
jmp @b
.space:
dec edi
inc ecx
cmp ecx, [ebx+DISK.NumPartitions]
jb .partitions
; 3. Reclaim unused memory, if any.
mov [ramdisk_actual_size], edx
add edx, 7 ; aligning up
shr edx, 3 ; 512-byte sectors -> 4096-byte pages
mov esi, RAMDISK_CAPACITY / 8 ; aligning down
sub esi, edx
jbe .no_reclaim
shl edx, 12
add edx, RAMDISK - OS_BASE
jmp @b
.found:
inc byte [edi]
add dword [esp], 8
jmp .zerorest
.break:
jecxz .noplace
inc edi
mov al, '1'
@@:
mov eax, edx
call free_page
add edx, 0x1000
dec esi
xchg al, [edi]
inc edi
cmp al, ' '
mov al, '0'
jnz @b
.no_reclaim:
pop esi ebx ; restore used registers to be stdcall
.succ:
pop edi
popad
clc
ret
.fail:
dbgstr 'Failed to initialize ramdisk'
pop esi ebx ; restore used registers to be stdcall
.noplace:
dec edi
cmp edi, [esp]
jz .err
add dword [esp], 8
mov word [edi], '~1'
inc edi
inc edi
@@:
mov byte [edi], '0'
.zerorest:
inc edi
cmp edi, [esp]
jb @b
pop edi
popad
;clc ; automatically
ret
endp
.err:
pop edi
popad
stc
ret
 
; Returns information about disk media.
proc ramdisk_querymedia
virtual at esp+4
.userdata dd ?
.info dd ?
end virtual
; Media is always present, sector size is always 512 bytes.
mov edx, [.userdata]
mov ecx, [.info]
mov [ecx+DISKMEDIAINFO.Flags], 0
mov [ecx+DISKMEDIAINFO.SectorSize], 512
mov eax, [ramdisk_actual_size]
mov dword [ecx+DISKMEDIAINFO.Capacity], eax
mov dword [ecx+DISKMEDIAINFO.Capacity+4], 0
; Return zero as an indicator of success.
fat_gen_short_name:
; in: esi->long name
; edi->buffer (8+3=11 chars)
; out: buffer filled
pushad
mov eax, ' '
push edi
stosd
stosd
stosd
pop edi
xor eax, eax
retn 8
endp
movi ebx, 8
lea ecx, [edi+8]
.loop:
lodsb
test al, al
jz .done
call char_toupper
cmp al, ' '
jz .space
cmp al, 80h
ja .big
test [fat_legal_chars+eax], 2
jnz .symbol
.inv_symbol:
mov al, '_'
or bh, 1
.symbol:
cmp al, '.'
jz .dot
.normal_symbol:
dec bl
jns .store
mov bl, 0
.space:
or bh, 1
jmp .loop
.store:
stosb
jmp .loop
.big:
cmp al, 0xB0
jb .normal_symbol
cmp al, 0xE0
jb .inv_symbol
cmp al, 0xF0
jb .normal_symbol
jmp .inv_symbol
.dot:
test bh, 2
jz .firstdot
pop ebx
add ebx, edi
sub ebx, ecx
push ebx
cmp ebx, ecx
jb @f
pop ebx
push ecx
@@:
cmp edi, ecx
jbe .skip
@@:
dec edi
mov al, [edi]
dec ebx
mov [ebx], al
mov byte [edi], ' '
cmp edi, ecx
ja @b
.skip:
mov bh, 3
jmp @f
.firstdot:
cmp bl, 8
jz .space
push edi
or bh, 2
@@:
mov edi, ecx
mov bl, 3
jmp .loop
.done:
test bh, 2
jz @f
pop edi
@@:
lea edi, [ecx-8]
test bh, 1
jz @f
call fat_next_short_name
@@:
popad
ret
 
; Common procedure for reading and writing.
; operation = 0 for reading, operation = 1 for writing.
; Arguments of ramdisk_read and ramdisk_write are the same.
macro ramdisk_read_write operation
{
push esi edi ; save used registers to be stdcall
mov esi, [userdata]
mov edi, [numsectors_ptr]
; 1. Determine number of sectors to be transferred.
; This is either the requested number of sectors or number of sectors
; up to the disk boundary, depending of what is less.
;----------------------------------------------------------------
;
; fs_RamdiskRewrite - LFN variant for writing ramdisk
; fs_RamdiskCreateFolder - create folder on ramdisk
;
; esi points to file/folder name
; ebx ignored (reserved)
; ecx number of bytes to write, 0+ (ignored for folders)
; edx mem location to data (ignored for folders)
;
; ret ebx = number of written bytes
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
@@:
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
 
fs_RamdiskCreateFolder:
mov al, 1 ; create folder
jmp fs_RamdiskRewrite.common
 
fs_RamdiskRewrite:
xor eax, eax ; create file
.common:
cmp byte [esi], 0
jz @b
pushad
xor edi, edi
push esi
test ebp, ebp
jz @f
mov esi, ebp
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
lea edi, [esi-1]
jmp @b
@@:
pop esi
test edi, edi
jnz .noroot
test ebp, ebp
jnz .hasebp
push ramdisk_root_extend_dir
push ramdisk_root_next_write
push edi
push ramdisk_root_first
push ramdisk_root_next
jmp .common1
.hasebp:
mov eax, ERROR_ACCESS_DENIED
cmp byte [ebp], 0
jz .ret1
push ebp
xor ebp, ebp
call rd_find_lfn
pop esi
jc .notfound0
jmp .common0
.noroot:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edi+1], 0
jz .ret1
; check existence
mov byte [edi], 0
push edi
call rd_find_lfn
pop esi
mov byte [esi], '/'
jnc @f
.notfound0:
mov eax, ERROR_FILE_NOT_FOUND
.ret1:
mov [esp+28], eax
popad
xor ebx, ebx
ret
@@:
inc esi
.common0:
test byte [edi+11], 0x10 ; must be directory
mov eax, ERROR_ACCESS_DENIED
jz .ret1
movzx ebp, word [edi+26] ; ebp=cluster
mov eax, ERROR_FAT_TABLE
cmp ebp, 2
jb .ret1
cmp ebp, 2849
jae .ret1
push ramdisk_notroot_extend_dir
push ramdisk_notroot_next_write
push ebp
push ramdisk_notroot_first
push ramdisk_notroot_next
.common1:
call fat_find_lfn
jc .notfound
; found
test byte [edi+11], 10h
jz .exists_file
; found directory; if we are creating directory, return OK,
; if we are creating file, say "access denied"
add esp, 20
popad
test al, al
mov eax, ERROR_ACCESS_DENIED
jz @f
mov al, 0
@@:
xor ebx, ebx
ret
.exists_file:
; found file; if we are creating directory, return "access denied",
; if we are creating file, delete existing file and continue
cmp byte [esp+20+28], 0
jz @f
add esp, 20
popad
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
@@:
; delete FAT chain
push edi
xor eax, eax
mov dword [edi+28], eax ; zero size
xchg ax, word [edi+26] ; start cluster
test eax, eax
jz .done1
@@:
cmp eax, 0xFF8
jae .done1
lea edi, [RAMDISK_FAT + eax*2] ; position in FAT
xor eax, eax
xchg ax, [edi]
jmp @b
.done1:
pop edi
call get_time_for_file
mov [edi+22], ax
call get_date_for_file
mov [edi+24], ax
mov [edi+18], ax
or byte [edi+11], 20h ; set 'archive' attribute
jmp .doit
.notfound:
; file is not found; generate short name
call fat_name_is_legal
jc @f
add esp, 20
popad
mov eax, ERROR_FILE_NOT_FOUND
xor ebx, ebx
ret
@@:
sub esp, 12
mov edi, esp
call fat_gen_short_name
.test_short_name_loop:
push esi edi ecx
mov esi, edi
lea eax, [esp+12+12+8]
mov [eax], ebp
call dword [eax-4]
jc .found
.test_short_name_entry:
cmp byte [edi+11], 0xF
jz .test_short_name_cont
mov ecx, 11
push esi edi
repz cmpsb
pop edi esi
jz .short_name_found
.test_short_name_cont:
lea eax, [esp+12+12+8]
call dword [eax-8]
jnc .test_short_name_entry
jmp .found
.short_name_found:
pop ecx edi esi
call fat_next_short_name
jnc .test_short_name_loop
.disk_full:
add esp, 12+20
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.found:
pop ecx edi esi
; now find space in directory
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
mov al, '~'
push ecx edi
mov ecx, 8
repnz scasb
movi eax, 1 ; 1 entry
jnz .notilde
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
xor eax, eax
@@:
cmp byte [esi], 0
jz @f
inc esi
inc eax
jmp @b
@@:
sub esi, eax
add eax, 12+13
mov ecx, 13
push edx
cdq
div ecx
pop edx
.notilde:
push -1
push -1
; find <eax> successive entries in directory
xor ecx, ecx
; 1a. Test whether [start_sector] is less than RAMDISK_CAPACITY.
; If so, calculate number of sectors between [start_sector] and RAMDISK_CAPACITY.
; Otherwise, the actual number of sectors is zero.
cmp dword [start_sector+4], ecx
jnz .got_number
mov eax, [ramdisk_actual_size]
sub eax, dword [start_sector]
jbe .got_number
; 1b. Get the requested number of sectors.
mov ecx, [edi]
; 1c. If it is greater than number of sectors calculated in 1a, use the value
; from 1a.
push eax
lea eax, [esp+12+8+12+8]
mov [eax], ebp
call dword [eax-4]
pop eax
.scan_dir:
cmp byte [edi], 0
jz .free
cmp byte [edi], 0xE5
jz .free
xor ecx, ecx
.scan_cont:
push eax
lea eax, [esp+12+8+12+8]
call dword [eax-8]
pop eax
jnc .scan_dir
push eax
lea eax, [esp+12+8+12+8]
call dword [eax+8] ; extend directory
pop eax
jnc .scan_dir
add esp, 8+8+12+20
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.free:
test ecx, ecx
jnz @f
mov [esp], edi
mov ecx, [esp+8+8+12+8]
mov [esp+4], ecx
xor ecx, ecx
@@:
inc ecx
cmp ecx, eax
jb .got_number
mov ecx, eax
.got_number:
; 2. Compare the actual number of sectors with requested. If they are
; equal, set eax (it will be the returned value) to zero. Otherwise,
; use DISK_STATUS_END_OF_MEDIA.
jb .scan_cont
; found!
; If creating a directory, allocate one data cluster now and fail immediately
; if this is impossible. This prevents from creating an invalid directory entry
; on a full disk.
; yup, the argument is quite non-intuitive... but what should I do if
; the entire function uses such arguments? BTW, it refers to al from pushad,
; which in turn is filled with 0 in fs_RamdiskRewrite and 1 in fs_RamdiskCreateFolder.
push esi ecx
cmp byte [esp+24+12+20+28], 0
jz .no.preallocate.folder.data
mov ecx, 2849
mov edi, RAMDISK_FAT
xor eax, eax
cmp ecx, [edi]
repnz scasw
jz @f
mov al, DISK_STATUS_END_OF_MEDIA
add esp, 24
jmp .disk_full
@@:
; 3. Store the actual number of sectors.
mov [edi], ecx
; 4. Calculate source and destination addresses.
if operation = 0 ; reading?
mov esi, dword [start_sector]
shl esi, 9
add esi, RAMDISK
mov edi, [buffer]
else ; writing?
mov edi, dword [start_sector]
mov [esp+24+12+20+20], edi ; store the cluster somewhere
.no.preallocate.folder.data:
; calculate name checksum
mov esi, [esp+8+8]
mov ecx, 11
xor eax, eax
@@:
ror al, 1
add al, [esi]
inc esi
loop @b
pop ecx esi
pop edi
pop dword [esp+8+12+8]
; edi points to last entry in free chunk
dec ecx
jz .nolfn
push esi
push eax
mov al, 40h
.writelfn:
or al, cl
mov esi, [esp+4]
push ecx
dec ecx
imul ecx, 13
add esi, ecx
stosb
mov cl, 5
call .read_symbols
mov ax, 0xF
stosw
mov al, [esp+4]
stosb
mov cl, 6
call .read_symbols
xor eax, eax
stosw
mov cl, 2
call .read_symbols
pop ecx
lea eax, [esp+8+8+12+8]
call dword [eax+4] ; next write
xor eax, eax
loop .writelfn
pop eax
pop esi
.nolfn:
xchg esi, [esp]
mov ecx, 11
rep movsb
mov word [edi], 20h ; attributes
sub edi, 11
pop esi ecx
add esp, 12
mov byte [edi+13], 0 ; tenths of a second at file creation time
call get_time_for_file
mov [edi+14], ax ; creation time
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+16], ax ; creation date
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
and word [edi+20], 0 ; high word of cluster
and word [edi+26], 0 ; low word of cluster - to be filled
and dword [edi+28], 0 ; file size - to be filled
cmp byte [esp+20+28], 0
jz .doit
; create directory
mov byte [edi+11], 10h ; attributes: folder
mov ecx, 32*2
mov edx, edi
push edx
push ecx
push edi
add edi, 26 ; edi points to low word of cluster
push edi
mov edi, [esp+16+20+20]
jmp .doit2
.doit:
push edx
push ecx
push edi
add edi, 26 ; edi points to low word of cluster
push edi
jecxz .done
mov ecx, 2849
mov edi, RAMDISK_FAT
.write_loop:
; allocate new cluster
xor eax, eax
repnz scasw
jnz .disk_full2
.doit2:
dec edi
dec edi
 
; lea eax, [edi-(RAMDISK_FAT)]
 
mov eax, edi
sub eax, RAMDISK_FAT
 
shr eax, 1 ; eax = cluster
mov word [edi], 0xFFF ; mark as last cluster
xchg edi, [esp]
stosw
pop edi
push edi
inc ecx
; write data
cmp byte [esp+16+20+28], 0
jnz .writedir
shl eax, 9
add eax, RAMDISK+31*512
.writefile:
mov ebx, edx
xchg eax, ebx
push ecx
mov ecx, 512
cmp dword [esp+12], ecx
jae @f
mov ecx, [esp+12]
@@:
call memmove
add edx, ecx
sub [esp+12], ecx
pop ecx
jnz .write_loop
.done:
mov ebx, edx
pop edi edi ecx edx
sub ebx, edx
mov [edi+28], ebx
add esp, 20
mov [esp+16], ebx
popad
xor eax, eax
ret
.disk_full2:
mov ebx, edx
pop edi edi ecx edx
sub ebx, edx
mov [edi+28], ebx
add esp, 20
mov [esp+16], ebx
popad
movi eax, ERROR_DISK_FULL
ret
.writedir:
mov edi, eax
shl edi, 9
add edi, RAMDISK
mov esi, [buffer]
end if
; 5. Calculate number of dwords to be transferred.
shl ecx, 9-2
; 6. Copy data.
add edi, RAMDISK+31*512
mov esi, edx
mov ecx, 32/4
push ecx
rep movsd
; 7. Return. The value in eax was calculated in step 2.
pop edi esi ; restore used registers to be stdcall
}
mov dword [edi-32], '. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov word [edi-32+26], ax
mov esi, edx
pop ecx
rep movsd
mov dword [edi-32], '.. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov eax, [esp+16+8]
mov word [edi-32+26], ax
xor eax, eax
mov ecx, (512-32*2)/4
rep stosd
pop edi edi ecx edx
add esp, 20
popad
xor eax, eax
xor ebx, ebx
ret
 
; Reads one or more sectors from the device.
proc ramdisk_read userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
ramdisk_read_write 0
.read_symbol:
or ax, -1
test esi, esi
jz .retFFFF
lodsb
test al, al
jnz ansi2uni_char
xor eax, eax
xor esi, esi
.retFFFF:
ret
endp
 
; Writes one or more sectors to the device.
proc ramdisk_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
ramdisk_read_write 1
.read_symbols:
call .read_symbol
stosw
loop .read_symbols
ret
endp
 
; The kernel calls this function when initializing cache subsystem for
; the media. This call allows the driver to adjust the cache size.
proc ramdisk_adjust_cache_size
virtual at esp+4
.userdata dd ?
.suggested_size dd ?
end virtual
; Since ramdisk does not need cache, just return 0.
;----------------------------------------------------------------
;
; fs_RamdiskWrite - LFN variant for writing to sys floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = bytes written (maybe 0)
; eax = 0 ok write or other = errormsg
;
;--------------------------------------------------------------
@@:
push ERROR_ACCESS_DENIED
fs_RamdiskWrite.ret0:
pop eax
xor ebx, ebx
ret
 
fs_RamdiskWrite:
cmp byte [esi], 0
jz @b
pushad
call rd_find_lfn
jnc .found
popad
push ERROR_FILE_NOT_FOUND
jmp .ret0
.found:
; must not be directory
test byte [edi+11], 10h
jz @f
popad
push ERROR_ACCESS_DENIED
jmp .ret0
@@:
; FAT does not support files larger than 4GB
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
.eof:
popad
push ERROR_END_OF_FILE
jmp .ret0
@@:
mov ebx, [ebx]
.l1:
; now edi points to direntry, ebx=start byte to write,
; ecx=number of bytes to write, edx=data pointer
call fat_update_datetime
 
; extend file if needed
add ecx, ebx
jc .eof ; FAT does not support files larger than 4GB
push 0 ; return value=0
cmp ecx, [edi+28]
jbe .length_ok
cmp ecx, ebx
jz .length_ok
call ramdisk_extend_file
jnc .length_ok
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
; First case is fatal error, in second case we may write some data
mov [esp], eax
cmp al, ERROR_DISK_FULL
jz .disk_full
pop eax
mov [esp+28], eax
popad
xor ebx, ebx
ret
.disk_full:
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
.ret:
pop eax
mov [esp+28], eax ; eax=return value
sub edx, [esp+20]
mov [esp+16], edx ; ebx=number of written bytes
popad
ret
.length_ok:
; now ebx=start pos, ecx=end pos, both lie inside file
sub ecx, ebx
jz .ret
movzx edi, word [edi+26] ; starting cluster
.write_loop:
sub ebx, 0x200
jae .next_cluster
push ecx
neg ebx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
mov eax, edi
shl eax, 9
add eax, RAMDISK+31*512+0x200
sub eax, ebx
mov ebx, eax
mov eax, edx
call memmove
xor ebx, ebx
add edx, ecx
sub [esp], ecx
pop ecx
jz .ret
.next_cluster:
movzx edi, word [edi*2+RAMDISK_FAT]
jmp .write_loop
 
ramdisk_extend_file.zero_size:
xor eax, eax
retn 8
endp
jmp ramdisk_extend_file.start_extend
 
; extends file on ramdisk to given size, new data area is filled by 0
; in: edi->direntry, ecx=new size
; out: CF=0 => OK, eax=0
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
ramdisk_extend_file:
push ecx
; find the last cluster of file
movzx eax, word [edi+26] ; first cluster
mov ecx, [edi+28]
jecxz .zero_size
@@:
sub ecx, 0x200
jbe @f
mov eax, [eax*2+RAMDISK_FAT]
and eax, 0xFFF
jz .fat_err
cmp eax, 0xFF8
jb @b
.fat_err:
pop ecx
movi eax, ERROR_FAT_TABLE
stc
ret
@@:
push eax
mov eax, [eax*2+RAMDISK_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
pop eax
jb .fat_err
; set length to full number of sectors and make sure that last sector is zero-padded
sub [edi+28], ecx
push eax edi
mov edi, eax
shl edi, 9
lea edi, [edi+RAMDISK+31*512+0x200+ecx]
neg ecx
xor eax, eax
rep stosb
pop edi eax
.start_extend:
pop ecx
; now do extend
push edx esi
mov esi, RAMDISK_FAT+2*2 ; start scan from cluster 2
mov edx, 2847 ; number of clusters to scan
.extend_loop:
cmp [edi+28], ecx
jae .extend_done
; add new sector
push ecx
mov ecx, edx
push edi
mov edi, esi
jecxz .disk_full
push eax
xor eax, eax
repnz scasw
pop eax
jnz .disk_full
mov word [edi-2], 0xFFF
mov esi, edi
mov edx, ecx
sub edi, RAMDISK_FAT
shr edi, 1
dec edi ; now edi=new cluster
test eax, eax
jz .first_cluster
mov [RAMDISK_FAT+eax*2], di
jmp @f
.first_cluster:
pop eax ; eax->direntry
push eax
mov [eax+26], di
@@:
push edi
shl edi, 9
add edi, RAMDISK+31*512
xor eax, eax
mov ecx, 512/4
rep stosd
pop eax ; eax=new cluster
pop edi ; edi->direntry
pop ecx ; ecx=required size
add dword [edi+28], 0x200
jmp .extend_loop
.extend_done:
mov [edi+28], ecx
pop esi edx
xor eax, eax ; CF=0
ret
.disk_full:
pop edi ecx
pop esi edx
stc
movi eax, ERROR_DISK_FULL
ret
 
fat_update_datetime:
call get_time_for_file
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskSetFileEnd - set end of file on ramdisk
;
; esi points to filename
; ebx points to 64-bit number = new file size
; ecx ignored (reserved)
; edx ignored (reserved)
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskSetFileEnd:
cmp byte [esi], 0
jnz @f
.access_denied:
push ERROR_ACCESS_DENIED
jmp .ret
@@:
push edi
call rd_find_lfn
jnc @f
pop edi
push ERROR_FILE_NOT_FOUND
.ret:
pop eax
ret
@@:
; must not be directory
test byte [edi+11], 10h
jz @f
pop edi
jmp .access_denied
@@:
; file size must not exceed 4Gb
cmp dword [ebx+4], 0
jz @f
pop edi
push ERROR_END_OF_FILE
jmp .ret
@@:
; set file modification date/time to current
call fat_update_datetime
mov eax, [ebx]
cmp eax, [edi+28]
jb .truncate
ja .expand
pop edi
xor eax, eax
ret
.expand:
push ecx
mov ecx, eax
call ramdisk_extend_file
pop ecx
pop edi
ret
.truncate:
mov [edi+28], eax
push ecx
movzx ecx, word [edi+26]
test eax, eax
jz .zero_size
; find new last sector
@@:
sub eax, 0x200
jbe @f
movzx ecx, word [RAMDISK_FAT+ecx*2]
jmp @b
@@:
; zero data at the end of last sector
push ecx
mov edi, ecx
shl edi, 9
lea edi, [edi+RAMDISK+31*512+eax+0x200]
mov ecx, eax
neg ecx
xor eax, eax
rep stosb
pop ecx
; terminate FAT chain
lea ecx, [RAMDISK_FAT+ecx+ecx]
push dword [ecx]
mov word [ecx], 0xFFF
pop ecx
and ecx, 0xFFF
jmp .delete
.zero_size:
and word [edi+26], 0
.delete:
; delete FAT chain starting with ecx
; mark all clusters as free
cmp ecx, 0xFF8
jae .deleted
lea ecx, [RAMDISK_FAT+ecx+ecx]
push dword [ecx]
and word [ecx], 0
pop ecx
and ecx, 0xFFF
jmp .delete
.deleted:
pop ecx
pop edi
xor eax, eax
ret
 
fs_RamdiskGetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call rd_find_lfn
fs_GetFileInfo_finish:
jnc @f
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
@@:
push esi ebp
xor ebp, ebp
mov esi, edx
and dword [esi+4], 0
call fat_entry_to_bdfe2
pop ebp esi
pop edi
xor eax, eax
ret
 
fs_RamdiskSetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call rd_find_lfn
jnc @f
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
@@:
call bdfe_to_fat_entry
pop edi
xor eax, eax
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskDelete - delete file or empty folder from ramdisk
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskDelete:
cmp byte [esi], 0
jnz @f
; cannot delete root!
.access_denied:
push ERROR_ACCESS_DENIED
.pop_ret:
pop eax
ret
@@:
and [rd_prev_sector], 0
and [rd_prev_prev_sector], 0
push edi
call rd_find_lfn
jnc .found
pop edi
push ERROR_FILE_NOT_FOUND
jmp .pop_ret
.found:
cmp dword [edi], '. '
jz .access_denied2
cmp dword [edi], '.. '
jz .access_denied2
test byte [edi+11], 10h
jz .dodel
; we can delete only empty folders!
movzx eax, word [edi+26]
push ebx
mov ebx, eax
shl ebx, 9
add ebx, RAMDISK + 31*0x200 + 2*0x20
.checkempty:
cmp byte [ebx], 0
jz .empty
cmp byte [ebx], 0xE5
jnz .notempty
add ebx, 0x20
test ebx, 0x1FF
jnz .checkempty
movzx eax, word [RAMDISK_FAT + eax*2]
test eax, eax
jz .empty
mov ebx, eax
shl ebx, 9
add ebx, RAMDISK + 31*0x200
jmp .checkempty
.notempty:
pop ebx
.access_denied2:
pop edi
jmp .access_denied
.empty:
pop ebx
.dodel:
movzx eax, word [edi+26]
; delete folder entry
mov byte [edi], 0xE5
; delete LFN (if present)
.lfndel:
test edi, 0x1FF
jnz @f
cmp [rd_prev_sector], 0
jz @f
cmp [rd_prev_sector], -1
jz .lfndone
mov edi, [rd_prev_sector]
push [rd_prev_prev_sector]
pop [rd_prev_sector]
or [rd_prev_prev_sector], -1
shl edi, 9
add edi, RAMDISK + 31*0x200 + 0x200
@@:
sub edi, 0x20
cmp byte [edi], 0xE5
jz .lfndone
cmp byte [edi+11], 0xF
jnz .lfndone
mov byte [edi], 0xE5
jmp .lfndel
.lfndone:
; delete FAT chain
cmp eax, 2
jb .done
cmp eax, 0xFF8
jae .done
lea eax, [RAMDISK_FAT + eax*2]
push dword [eax]
and word [eax], 0
pop eax
and eax, 0xFFF
jmp .lfndone
.done:
pop edi
xor eax, eax
ret
 
; \end{diamond}
/kernel/branches/Kolibri-acpi/blkdev/rdsave.inc
13,8 → 13,7
dd 2 ; subfunction: write
dd 0 ; (reserved)
dd 0 ; (reserved)
.size:
dd 0
dd 1440*1024 ; size 1440 Kb
dd RAMDISK
db 0
.name:
21,11 → 20,9
dd ?
endg
sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only)
call restorefatchain
mov ebx, saverd_fileinfo
mov [ebx+21], ecx
mov eax, [ramdisk_actual_size]
shl eax, 9
mov [ebx+12], eax
mov [saverd_fileinfo.name], ecx
pushad
call file_system_lfn_protected ;in ebx
popad
/kernel/branches/Kolibri-acpi/boot/booteng.inc
0,0 → 1,101
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;======================================================================
;
; BOOT DATA
;
;======================================================================
 
$Revision$
 
 
d80x25_bottom:
db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY '
db 'NO WARRANTY ',186
db 186,' See file COPYING for details '
db ' ',186
line_full_bottom
d80x25_bottom_num = 3
 
msg_apm db " APM x.x ", 0
novesa db "Display: EGA/CGA",13,10,0
s_vesa db "Version of VESA: "
.ver db "?.?",13,10,0
 
gr_mode db "Select a videomode: ",13,10,0
 
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0
 
if defined extended_primary_loader
bdev db "Load ramdisk from [1-floppy; 2-kolibri.img]: ",0
else
bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);"
db 13,10,186," "
db "3-use preloaded ram-image from kernel restart;"
db 13,10,186," "
db "4-create blank image]: ",0
end if
 
prnotfnd db "Fatal - Videomode not found.",0
 
not386 db "Fatal - CPU 386+ required.",0
fatalsel db "Fatal - Graphics mode not supported by hardware.",0
pres_key db "Press any key to choose a new videomode.",0
badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0
memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0
okt db " ... OK"
linef db 13,10,0
diskload db "Loading diskette: 00 %",8,8,8,8,0
pros db "00"
backspace2 db 8,8,0
boot_dev db 0 ; 0=floppy, 1=hd
start_msg db "Press [abcd] to change settings, press [Enter] to continue booting",13,10,0
time_msg db " or wait "
time_str db " 5 seconds"
db " before automatical continuation",13,10,0
current_cfg_msg db "Current settings:",13,10,0
curvideo_msg db " [a] Videomode: ",0
 
mode0 db "320x200, EGA/CGA 256 colors",13,10,0
mode9 db "640x480, VGA 16 colors",13,10,0
 
usebd_msg db " [b] Add disks visible by BIOS:",0
on_msg db " on",13,10,0
off_msg db " off",13,10,0
 
preboot_device_msg db " [c] Floppy image: ",0
 
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "real floppy",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
pdm1 db "real floppy",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "use already loaded image",13,10,0
pdm4 db "create blank image",13,10,0
end if
 
loading_msg db "Loading KolibriOS...",0
 
if ~ defined extended_primary_loader
save_quest db "Remember current settings? [y/n]: ",0
loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0
end if
 
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0
 
remark1 db "Default values were selected to match most of configurations, but not all.",0
remark2 db "If the system does not boot, try to disable the item [b].",0
remarks dw remark1, remark2
num_remarks = 2
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/boot/boot_fat12.asm
0,0 → 1,302
; FAT12 boot sector for Kolibri OS
;
; Copyright (C) Alex Nogueira Teixeira
; Copyright (C) Diamond
; Copyright (C) Dmitry Kartashov aka shurf
;
; Distributed under GPL, see file COPYING for details
;
; Version 1.0
 
lf equ 0ah
cr equ 0dh
 
pos_read_tmp equ 0700h ;position for temporary read
boot_program equ 07c00h ;position for boot code
seg_read_kernel equ 01000h ;segment to kernel read
 
jmp start_program
nop
 
; Boot Sector and BPB Structure
BS_OEMName db 'KOLIBRI ' ; db 8
BPB_BytsPerSec dw 512 ; bytes per sector
BPB_SecPerClus db 1 ; sectors per cluster
BPB_RsvdSecCnt dw 1 ; number of reserver sectors
BPB_NumFATs db 2 ; count of FAT data structures
BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors)
BPB_TotSec16 dw 2880 ; count of sectors on the volume (2880 for 1.44 mbytes disk)
BPB_Media db 0f0h ; f0 - used for removable media
BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT
BPB_SecPerTrk dw 18 ; sectors per track
BPB_NumHeads dw 2 ; number of heads
BPB_HiddSec dd 0 ; count of hidden sectors
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535)
BS_DrvNum db 0 ; int 13h drive number
BS_Reserved db 0 ; reserved
BS_BootSig db 29h ; Extended boot signature
BS_VolID dd 0 ; Volume serial number
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11)
BS_FilSysType db 'FAT12 ' ; file system type (db 8)
 
start_program:
 
xor ax,ax
mov ss,ax
mov sp,boot_program
push ss
pop ds
 
; print loading string
mov si,loading+boot_program
loop_loading:
lodsb
or al,al
jz read_root_directory
mov ah,0eh
mov bx,7
int 10h
jmp loop_loading
 
read_root_directory:
push ss
pop es
 
; calculate some disk parameters
; - beginning sector of RootDir
mov ax,word [BPB_FATSz16+boot_program]
xor cx,cx
mov cl,byte [BPB_NumFATs+boot_program]
mul cx
add ax,word [BPB_RsvdSecCnt+boot_program]
mov word [FirstRootDirSecNum+boot_program],ax ; 19
mov si,ax
 
; - count of sectors in RootDir
mov bx,word [BPB_BytsPerSec+boot_program]
mov cl,5 ; divide ax by 32
shr bx,cl ; bx = directory entries per sector
mov ax,word [BPB_RootEntCnt+boot_program]
xor dx,dx
div bx
mov word [RootDirSecs+boot_program],ax ; 14
 
; - data start
add si,ax ; add beginning sector of RootDir and count sectors in RootDir
mov word [data_start+boot_program],si ; 33
; reading root directory
; al=count root dir sectrors !!!! TODO: al, max 255 sectors !!!!
mov ah,2 ; read
push ax
 
mov ax,word [FirstRootDirSecNum+boot_program]
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector)
pop ax
mov bx,pos_read_tmp ; es:bx read buffer
call read_sector
 
mov si,bx ; read buffer address: es:si
mov ax,[RootDirSecs+boot_program]
mul word [BPB_BytsPerSec+boot_program]
add ax,si ; AX = end of root dir. in buffer pos_read_tmp
 
; find kernel file in root directory
loop_find_dir_entry:
push si
mov cx,11
mov di,kernel_name+boot_program
rep cmpsb ; compare es:si and es:di, cx bytes long
pop si
je found_kernel_file
add si,32 ; next dir. entry
cmp si,ax ; end of directory
jb loop_find_dir_entry
 
file_error_message:
mov si,error_message+boot_program
 
loop_error_message:
lodsb
or al,al
jz freeze_pc
mov ah,0eh
mov bx,7
int 10h
jmp loop_error_message
 
freeze_pc:
jmp $ ; endless loop
 
; === KERNEL FOUND. LOADING... ===
 
found_kernel_file:
mov bp,[si+01ah] ; first cluster of kernel file
; <diamond>
mov [cluster1st+boot_program],bp ; starting cluster of kernel file
; <\diamond>
 
; reading first FAT table
mov ax,word [BPB_RsvdSecCnt+boot_program] ; begin first FAT abs sector number
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector)
mov bx,pos_read_tmp ; es:bx read position
mov ah,2 ; ah=2 (read)
mov al, byte [BPB_FATSz16+boot_program] ; FAT size in sectors (TODO: max 255 sectors)
call read_sector
jc file_error_message ; read error
 
mov ax,seg_read_kernel
mov es,ax
xor bx,bx ; es:bx = 1000h:0000h
 
 
; reading kernel file
loop_obtains_kernel_data:
; read one cluster of file
call obtain_cluster
jc file_error_message ; read error
 
; add one cluster length to segment:offset
push bx
mov bx,es
mov ax,word [BPB_BytsPerSec+boot_program] ;\
movsx cx,byte [BPB_SecPerClus+boot_program] ; | !!! TODO: !!!
mul cx ; | out this from loop !!!
shr ax,4 ;/
add bx,ax
mov es,bx
pop bx
 
mov di,bp
shr di,1
pushf
add di,bp ; di = bp * 1.5
add di,pos_read_tmp
mov ax,[di] ; read next entry from FAT-chain
popf
jc move_4_right
and ax,0fffh
jmp verify_end_sector
move_4_right:
mov cl,4
shr ax,cl
verify_end_sector:
cmp ax,0ff8h ; last cluster
jae execute_kernel
mov bp,ax
jmp loop_obtains_kernel_data
 
execute_kernel:
; <diamond>
mov ax,'KL'
push 0
pop ds
mov si,loader_block+boot_program
; </diamond>
push word seg_read_kernel
push word 0
retf ; jmp far 1000:0000
 
 
;------------------------------------------
; loading cluster from file to es:bx
obtain_cluster:
; bp - cluster number to read
; carry = 0 -> read OK
; carry = 1 -> read ERROR
 
; print one dot
push bx
mov ax,0e2eh ; ah=0eh (teletype), al='.'
xor bh,bh
int 10h
pop bx
 
writesec:
; convert cluster number to sector number
mov ax,bp ; data cluster to read
sub ax,2
xor dx,dx
mov dl,byte [BPB_SecPerClus+boot_program]
mul dx
add ax,word [data_start+boot_program]
 
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector)
patchhere:
mov ah,2 ; ah=2 (read)
mov al,byte [BPB_SecPerClus+boot_program] ; al=(one cluster)
call read_sector
retn
;------------------------------------------
 
;------------------------------------------
; read sector from disk
read_sector:
push bp
mov bp,20 ; try 20 times
newread:
dec bp
jz file_error_message
push ax bx cx dx
int 13h
pop dx cx bx ax
jc newread
pop bp
retn
;------------------------------------------
; convert abs. sector number (AX) to BIOS T:H:S
; sector number = (abs.sector%BPB_SecPerTrk)+1
; pre.track number = (abs.sector/BPB_SecPerTrk)
; head number = pre.track number%BPB_NumHeads
; track number = pre.track number/BPB_NumHeads
; Return: cl - sector number
; ch - track number
; dl - drive number (0 = a:)
; dh - head number
conv_abs_to_THS:
push bx
mov bx,word [BPB_SecPerTrk+boot_program]
xor dx,dx
div bx
inc dx
mov cl, dl ; cl = sector number
mov bx,word [BPB_NumHeads+boot_program]
xor dx,dx
div bx
; !!!!!!! ax = track number, dx = head number
mov ch,al ; ch=track number
xchg dh,dl ; dh=head number
mov dl,0 ; dl=0 (drive 0 (a:))
pop bx
retn
;------------------------------------------
 
loading db cr,lf,'Starting system ',00h
error_message db 13,10
kernel_name db 'KERNEL MNT ?',cr,lf,00h
FirstRootDirSecNum dw ?
RootDirSecs dw ?
data_start dw ?
 
; <diamond>
write1st:
push cs
pop ds
mov byte [patchhere+1+boot_program], 3 ; change ah=2 to ah=3
mov bp,[cluster1st+boot_program]
push 1000h
pop es
xor bx,bx
call writesec
mov byte [patchhere+1+boot_program], 2 ; change back ah=3 to ah=2
retf
cluster1st dw ?
loader_block:
db 1
dw 0
dw write1st+boot_program
dw 0
; <\diamond>
 
times 0x1fe-$ db 00h
 
db 55h,0aah ;boot signature
/kernel/branches/Kolibri-acpi/data32.inc
51,7 → 51,7
if lang eq ru
boot_initirq cp866 'Инициализация IRQ',0
boot_picinit cp866 'Инициализация PIC',0
boot_v86machine cp866 'Инициализация системной V86 машины',0
boot_v86machine cp866 'Инициализация системы V86 машины',0
boot_inittimer cp866 'Инициализация системного таймера (IRQ0)',0
boot_initapic cp866 'Попытка инициализации APIC',0
boot_enableirq cp866 'Включить прерывания 2, 13',0
69,7 → 69,6
boot_cpuid cp866 'Чтение CPUIDs',0
; boot_devices cp866 'Поиск устройств',0
boot_timer cp866 'Установка таймера',0
boot_initramdisk cp866 'Инициализация рамдиска',0
boot_irqs cp866 'Переопределение IRQ',0
boot_setmouse cp866 'Установка мыши',0
boot_windefs cp866 'Установка настроек окон по умолчанию',0
99,7 → 98,6
boot_picinit db 'Initialize PIC',0
boot_v86machine db 'Initialize system V86 machine',0
boot_inittimer db 'Initialize system timer (IRQ0)',0
boot_initramdisk db 'Initialize ramdisk',0
boot_initapic db 'Try to initialize APIC',0
boot_enableirq db 'Enable interrupts 2, 13',0
boot_disabling_ide db 'Disable interrupts in IDE controller',0
174,13 → 172,7
 
vmode db '/sys/drivers/VMODE.MDR',0
;vrr_m db 'VRR_M',0
kernel_file_load:
; load kernel.mnt to 0x7000:0
dd 0 ; subfunction
dq 0 ; offset in file
dd 0x30000 ; number of bytes to read
dd OS_BASE + 0x70000 ; buffer for data
db '/RD/1/KERNEL.MNT',0
kernel_file db 'KERNEL MNT'
 
dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0
 
578,7 → 570,8
org (OS_BASE+0x0100000)
 
RAMDISK: rb 2880*512
rb 2856*4 ; not used
RAMDISK_FAT: rb 2856*2
FLOPPY_FAT: rb 2856*2
 
_CLEAN_ZONE:
 
/kernel/branches/Kolibri-acpi/data32et.inc
2,7 → 2,6
boot_picinit latin1 'Algväärtustan PIC',0
boot_v86machine latin1 'Algväärtustan süsteemi V86 masinat',0
boot_inittimer latin1 'Algväärtustan süsteemi taimerit (IRQ0)',0
boot_initramdisk latin1 'Initialize ramdisk',0
boot_initapic latin1 'Proovin Algväärtustada APIC',0
boot_enableirq latin1 'Luban katkestused 2, 13',0
boot_disabling_ide latin1 'Keelan IDE kontrolleri katkestused',0
/kernel/branches/Kolibri-acpi/detect/vortex86.inc
36,13 → 36,6
Vortex86SoCnum = ($ - Vortex86SoClist) / 4 ; Calculate the total number of known Vortex86 CPUs (if id=Vortex86SoCnum+1 --> unknown SoC)
endg
 
; When in debug mode, perform SoC detection regardless of the actual CPU vendor (even for vendors other than DMP)
; When in normal (not debug) mode, check the CPU vendor first, and perform SoC detection only if vendor is 'Vortex86 SoC'
if ~ VORTEX86DEBUG
cmp [cpu_vendor], 'Vort'
jnz .Vortex86end ; If the CPU vendor is not 'Vortex86 SoC', skip the SoC detection
end if
 
mov dx, 0xcf8 ; CF8h = Vortex86 PCI Configuration Address port
mov eax, 0x80000090 ; 0x80000090 = Starting PCI address to read from (32-bit register - accessed as DWORD)
out dx, eax ; Send request to PCI address port to retrieve data from this address
49,7 → 42,8
mov dx, 0xcfc ; CFCh = Vortex86 PCI Configuration Data port
in eax, dx ; Read data (SoC type) from PCI data port
 
if VORTEX86DEBUG ; When in debug mode, pretend that we received port output equal to "VORTEX86DEBUGVALUE"
if VORTEX86DEBUG
; // Used for debug purposes: testing in emulator and in non-Vortex86 CPU computers
mov eax, VORTEX86DEBUGVALUE
end if
61,9 → 55,10
cmp ax, 4d44h ; Check whether it's Vortex86 family (all Vortex86 SoC have ID in form of "0xNN504d44")
jnz .notVortex86
shr eax, 16 ; Discard lower word in EAX which is always 4d44h in Vortex86 family
cmp al, 50h ; The 3rd byte is always 50h in Vortex86 SoC (if this is the case, we need just the highest byte)
cmp al, 50h ; The 3rd byte is always 50h in Vortex86 SoC
jnz .notVortex86
mov bl, ah ; Copy SoC type to BL since EAX (that includes AH) is used implicitly in "LODSD" command below
shr ax, 8 ; Discard 3rd byte in EAX, the highest byte determines the SoC type
mov bl, al ; Copy SoC type to BL since EAX (that contains AL) is used implicitly in "LODSD" command below
mov esi, Vortex86SoClist ; ESI points to the start of Vortex86SoClist (used implicitly in "LODSD" command below)
xor ecx, ecx ; Zero ECX (it is used as counter)
cld ; Clears the DF flag in the EFLAGS register (DF=0 --> String operations increment ESI)
88,7 → 83,7
.unknownVortex86:
mov [Vortex86CPUid], cl ; Save the CPUid (Vortex86SoCnum+1=Unknown Vortex86)
DEBUGF 1, "unknown Vortex86 CPU (id=%d, last known is %d)\n", [Vortex86CPUid]:1, Vortex86SoCnum
DEBUGF 1, "unknown Vortex86 CPU (has id=%d, last known is %d)\n", [Vortex86CPUid]:1, Vortex86SoCnum
jmp .Vortex86end
.notVortex86: ; In case this register is used by other CPUs for other purpose, it's interesting what it contains
/kernel/branches/Kolibri-acpi/detect/dev_fd.inc
33,6 → 33,5
 
stdcall attach_int_handler, 6, FDCInterrupt, 0
DEBUGF 1, "K : Set IDE IRQ6 return code %x\n", eax
call floppy_init
@@:
 
/kernel/branches/Kolibri-acpi/drivers/vidrdc.asm
File deleted
\ No newline at end of file
/kernel/branches/Kolibri-acpi/drivers/usbhid/usbhid.asm
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbhid/sort.inc
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbhid/mouse.inc
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbhid/report.inc
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbhid/keyboard.inc
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbhid/unclaimed.inc
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbhid
Property changes:
Deleted: tsvn:logminsize
-5
\ No newline at end of property
/kernel/branches/Kolibri-acpi/drivers/fdo.inc
File deleted
/kernel/branches/Kolibri-acpi/drivers/apm.asm
File deleted
/kernel/branches/Kolibri-acpi/drivers/agp.asm
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbhid.asm
0,0 → 1,693
; standard driver stuff
format MS COFF
 
DEBUG = 1
 
; this is for DEBUGF macro from 'fdo.inc'
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
 
public START
public version
 
; USB constants
DEVICE_DESCR_TYPE = 1
CONFIG_DESCR_TYPE = 2
STRING_DESCR_TYPE = 3
INTERFACE_DESCR_TYPE = 4
ENDPOINT_DESCR_TYPE = 5
DEVICE_QUALIFIER_DESCR_TYPE = 6
 
CONTROL_PIPE = 0
ISOCHRONOUS_PIPE = 1
BULK_PIPE = 2
INTERRUPT_PIPE = 3
 
; USB structures
virtual at 0
config_descr:
.bLength db ?
.bDescriptorType db ?
.wTotalLength dw ?
.bNumInterfaces db ?
.bConfigurationValue db ?
.iConfiguration db ?
.bmAttributes db ?
.bMaxPower db ?
.sizeof:
end virtual
 
virtual at 0
interface_descr:
.bLength db ?
.bDescriptorType db ?
.bInterfaceNumber db ?
.bAlternateSetting db ?
.bNumEndpoints db ?
.bInterfaceClass db ?
.bInterfaceSubClass db ?
.bInterfaceProtocol db ?
.iInterface db ?
.sizeof:
end virtual
 
virtual at 0
endpoint_descr:
.bLength db ?
.bDescriptorType db ?
.bEndpointAddress db ?
.bmAttributes db ?
.wMaxPacketSize dw ?
.bInterval db ?
.sizeof:
end virtual
 
; Driver data for all devices
virtual at 0
device_data:
.type dd ? ; 1 = keyboard, 2 = mouse
.intpipe dd ? ; interrupt pipe handle
.packetsize dd ?
.packet rb 8 ; packet with data from device
.control rb 8 ; control packet to device
.sizeof:
end virtual
 
; Driver data for mouse
virtual at device_data.sizeof
mouse_data:
; no additional data
.sizeof:
end virtual
 
; Driver data for keyboard
virtual at device_data.sizeof
keyboard_data:
.handle dd ? ; keyboard handle from RegKeyboard
.configpipe dd ? ; config pipe handle
.prevpacket rb 8 ; previous packet with data from device
.timer dd ? ; auto-repeat timer handle
.repeatkey db ? ; auto-repeat key code
.ledstate db ? ; state of LEDs
align 4
.sizeof:
end virtual
 
section '.flat' code readable align 16
; The start procedure.
START:
; 1. Test whether the procedure is called with the argument DRV_ENTRY.
; If not, return 0.
xor eax, eax ; initialize return value
cmp dword [esp+4], 1 ; compare the argument
jnz .nothing
; 2. Register self as a USB driver.
; The name is my_driver = 'usbhid'; IOCTL interface is not supported;
; usb_functions is an offset of a structure with callback functions.
stdcall RegUSBDriver, my_driver, eax, usb_functions
; 3. Return the returned value of RegUSBDriver.
.nothing:
ret 4
 
; This procedure is called when new HID device is detected.
; It initializes the device.
AddDevice:
; Arguments are addressed through esp. In this point of the function,
; [esp+4] = a handle of the config pipe, [esp+8] points to config_descr
; structure, [esp+12] points to interface_descr structure.
; 1. Check device type. Currently only mice and keyboards with
; boot protocol are supported.
; 1a. Get the subclass and the protocol. Since bInterfaceSubClass and
; bInterfaceProtocol are subsequent in interface_descr, just one
; memory reference is used for both.
mov edx, [esp+12]
push ebx ; save used register to be stdcall
mov cx, word [edx+interface_descr.bInterfaceSubClass]
; 1b. For boot protocol, subclass must be 1 and protocol must be either 1 for
; a keyboard or 2 for a mouse. Check.
cmp cx, 0x0101
jz .keyboard
cmp cx, 0x0201
jz .mouse
; 1c. If the device is neither a keyboard nor a mouse, print a message and
; go to 6c.
DEBUGF 1,'K : unknown HID device\n'
jmp .nothing
; 1d. If the device is a keyboard or a mouse, print a message and continue
; configuring.
.keyboard:
DEBUGF 1,'K : USB keyboard detected\n'
push keyboard_data.sizeof
jmp .common
.mouse:
DEBUGF 1,'K : USB mouse detected\n'
push mouse_data.sizeof
.common:
; 2. Allocate memory for device data.
pop eax ; get size of device data
; 2a. Call the kernel, saving and restoring register edx.
push edx
call Kmalloc
pop edx
; 2b. Check result. If failed, say a message and go to 6c.
test eax, eax
jnz @f
DEBUGF 1,'K : no memory\n'
jmp .nothing
@@:
xchg eax, ebx
; HID devices use one IN interrupt endpoint for polling the device
; and an optional OUT interrupt endpoint. We do not use the later,
; but must locate the first. Look for the IN interrupt endpoint.
; 3. Get the upper bound of all descriptors' data.
mov eax, [esp+8+4] ; configuration descriptor
movzx ecx, [eax+config_descr.wTotalLength]
add eax, ecx
; 4. Loop over all descriptors until
; either end-of-data reached - this is fail
; or interface descriptor found - this is fail, all further data
; correspond to that interface
; or endpoint descriptor found.
; 4a. Loop start: eax points to the interface descriptor.
.lookep:
; 4b. Get next descriptor.
movzx ecx, byte [edx] ; the first byte of all descriptors is length
add edx, ecx
; 4c. Check that at least two bytes are readable. The opposite is an error.
inc edx
cmp edx, eax
jae .errorep
dec edx
; 4d. Check that this descriptor is not interface descriptor. The opposite is
; an error.
cmp byte [edx+endpoint_descr.bDescriptorType], INTERFACE_DESCR_TYPE
jz .errorep
; 4e. Test whether this descriptor is an endpoint descriptor. If not, continue
; the loop.
cmp byte [edx+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE
jnz .lookep
; 5. Check that the descriptor contains all required data and all data are
; readable. If so, proceed to 7.
cmp byte [edx+endpoint_descr.bLength], endpoint_descr.sizeof
jb .errorep
sub eax, endpoint_descr.sizeof
cmp edx, eax
jbe @f
; 6. An error occured during processing endpoint descriptor.
.errorep:
; 6a. Print a message.
DEBUGF 1,'K : error: invalid endpoint descriptor\n'
; 6b. Free memory allocated for device data.
.free:
xchg eax, ebx
call Kfree
.nothing:
; 6c. Return an error.
xor eax, eax
pop ebx
ret 12
@@:
; 7. Check that the endpoint is IN interrupt endpoint. If not, go to 6.
test [edx+endpoint_descr.bEndpointAddress], 80h
jz .errorep
mov cl, [edx+endpoint_descr.bmAttributes]
and cl, 3
cmp cl, INTERRUPT_PIPE
jnz .errorep
; 8. Open pipe for the endpoint.
; 8a. Load parameters from the descriptor.
movzx ecx, [edx+endpoint_descr.bEndpointAddress]
movzx eax, [edx+endpoint_descr.bInterval]
movzx edx, [edx+endpoint_descr.wMaxPacketSize]
; 8b. Call the kernel, saving and restoring edx.
push edx
stdcall USBOpenPipe, [esp+4+24], ecx, edx, INTERRUPT_PIPE, eax
pop edx
; 8c. Check result. If failed, go to 6b.
test eax, eax
jz .free
; We use 12 bytes for device type, interrupt pipe and interrupt packet size,
; 8 bytes for a packet and 8 bytes for previous packet, used by a keyboard.
; 9. Initialize device data.
mov [ebx+device_data.intpipe], eax
movi ecx, 8
cmp edx, ecx
jb @f
mov edx, ecx
@@:
xor eax, eax
mov [ebx+device_data.packetsize], edx
mov dword [ebx+device_data.packet], eax
mov dword [ebx+device_data.packet+4], eax
mov edx, [esp+12+4] ; interface descriptor
movzx ecx, [edx+interface_descr.bInterfaceProtocol]
mov [ebx+device_data.type], ecx
cmp ecx, 1
jnz @f
mov [ebx+keyboard_data.handle], eax
mov [ebx+keyboard_data.timer], eax
mov [ebx+keyboard_data.repeatkey], al
mov dword [ebx+keyboard_data.prevpacket], eax
mov dword [ebx+keyboard_data.prevpacket+4], eax
mov eax, [esp+4+4]
mov [ebx+keyboard_data.configpipe], eax
@@:
; 10. Send the control packet SET_PROTOCOL(Boot Protocol) to the interface.
lea eax, [ebx+device_data.control]
mov dword [eax], 21h + (0Bh shl 8) + (0 shl 16) ; class request to interface + SET_PROTOCOL + Boot protocol
and dword [eax+4], 0
mov dl, [edx+interface_descr.bInterfaceNumber]
mov [eax+4], dl
; Callback function is mouse_configured for mice and keyboard_configured1 for keyboards.
mov edx, keyboard_configured1
cmp ecx, 1
jz @f
mov edx, mouse_configured
@@:
stdcall USBControlTransferAsync, [esp+4+28], eax, 0, 0, edx, ebx, 0
; 11. Return with pointer to device data as returned value.
xchg eax, ebx
pop ebx
ret 12
 
; This function is called when SET_PROTOCOL command for keyboard is done,
; either successful or unsuccessful.
keyboard_configured1:
xor edx, edx
; 1. Check the status of the transfer.
; If the transfer was failed, go to the common error handler.
cmp dword [esp+8], edx ; status is zero?
jnz keyboard_data_ready.error
; 2. Send the control packet SET_IDLE(infinity). HID auto-repeat is not useful.
mov eax, [esp+20]
push edx ; flags for USBControlTransferAsync
push eax ; userdata for USBControlTransferAsync
add eax, device_data.control
mov dword [eax], 21h + (0Ah shl 8) + (0 shl 24) ; class request to interface + SET_IDLE + no autorepeat
stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \
eax, edx, edx, keyboard_configured2; , <userdata>, <flags>
; 3. Return.
ret 20
 
; This function is called when SET_IDLE command for keyboard is done,
; either successful or unsuccessful.
keyboard_configured2:
; Check the status of the transfer and go to the corresponding label
; in the main handler.
cmp dword [esp+8], 0
jnz keyboard_data_ready.error
mov edx, [esp+20]
push edx
stdcall RegKeyboard, usbkbd_functions, edx
pop edx
mov [edx+keyboard_data.handle], eax
jmp keyboard_data_ready.next
 
; This function is called when another interrupt packet arrives,
; processed either successfully or unsuccessfully.
; It should parse the packet and initiate another transfer with
; the same callback function.
keyboard_data_ready:
; 1. Check the status of the transfer.
mov eax, [esp+8]
test eax, eax
jnz .error
; Parse the packet, comparing with the previous packet.
; For boot protocol, USB keyboard packet consists of the first byte
; with status keys that are currently pressed. The second byte should
; be ignored, and other 5 bytes denote keys that are currently pressed.
push esi ebx ; save used registers to be stdcall
; 2. Process control keys.
; 2a. Initialize before loop for control keys. edx = mask for control bits
; that were changed.
mov ebx, [esp+20+8]
movzx edx, byte [ebx+device_data.packet] ; get state of control keys
xor dl, byte [ebx+keyboard_data.prevpacket] ; compare with previous state
; 2b. If state of control keys has not changed, advance to 3.
jz .nocontrol
; 2c. Otherwise, loop over control keys; esi = bit number.
xor esi, esi
.controlloop:
; 2d. Skip bits that have not changed.
bt edx, esi
jnc .controlnext
push edx ; save register which is possibly modified by API
; The state of the current control key has changed.
; 2e. For extended control keys, send the prefix 0xE0.
mov al, [control_keys+esi]
test al, al
jns @f
push eax
mov ecx, 0xE0
call SetKeyboardData
pop eax
and al, 0x7F
@@:
; 2f. If the current state of the control key is "pressed", send normal
; scancode. Otherwise, the key is released, so set the high bit in scancode.
movzx ecx, al
bt dword [ebx+device_data.packet], esi
jc @f
or cl, 0x80
@@:
call SetKeyboardData
pop edx ; restore register which was possibly modified by API
.controlnext:
; 2g. We have 8 control keys.
inc esi
cmp esi, 8
jb .controlloop
.nocontrol:
; 3. Initialize before loop for normal keys. esi = index.
movi esi, 2
.normalloop:
; 4. Process one key which was pressed in the previous packet.
; 4a. Get the next pressed key from the previous packet.
movzx eax, byte [ebx+esi+keyboard_data.prevpacket]
; 4b. Ignore special codes.
cmp al, 3
jbe .normalnext1
; 4c. Ignore keys that are still pressed in the current packet.
lea ecx, [ebx+device_data.packet]
call haskey
jz .normalnext1
; 4d. Say warning about keys with strange codes.
cmp eax, normal_keys_number
jae .badkey1
movzx ecx, [normal_keys+eax]
jecxz .badkey1
; 4e. For extended keys, send the prefix 0xE0.
push ecx ; save keycode
test cl, cl
jns @f
push ecx
mov ecx, 0xE0
call SetKeyboardData
pop ecx
@@:
; 4f. Send the release event.
or cl, 0x80
call SetKeyboardData
; 4g. If this key is autorepeating, stop the timer.
pop ecx ; restore keycode
cmp cl, [ebx+keyboard_data.repeatkey]
jnz .normalnext1
mov eax, [ebx+keyboard_data.timer]
test eax, eax
jz .normalnext1
stdcall CancelTimerHS, eax
and [ebx+keyboard_data.timer], 0
jmp .normalnext1
.badkey1:
DEBUGF 1,'K : unknown keycode: %x\n',al
.normalnext1:
; 5. Process one key which is pressed in the current packet.
; 5a. Get the next pressed key from the current packet.
movzx eax, byte [ebx+esi+device_data.packet]
; 5b. Ignore special codes.
cmp al, 3
jbe .normalnext2
; 5c. Ignore keys that were already pressed in the previous packet.
lea ecx, [ebx+keyboard_data.prevpacket]
call haskey
jz .normalnext2
; 5d. Say warning about keys with strange codes.
cmp eax, normal_keys_number
jae .badkey2
movzx ecx, [normal_keys+eax]
jecxz .badkey2
; 5e. For extended keys, send the prefix 0xE0.
push ecx ; save keycode
test cl, cl
jns @f
push ecx
mov ecx, 0xE0
call SetKeyboardData
pop ecx
@@:
; 5f. Send the press event.
and cl, not 0x80
call SetKeyboardData
; 5g. Stop the current auto-repeat timer, if present.
mov eax, [ebx+keyboard_data.timer]
test eax, eax
jz @f
stdcall CancelTimerHS, eax
@@:
; 5h. Start the auto-repeat timer.
pop ecx ; restore keycode
mov [ebx+keyboard_data.repeatkey], cl
stdcall TimerHS, 25, 5, autorepeat_timer, ebx
mov [ebx+keyboard_data.timer], eax
jmp .normalnext2
.badkey2:
DEBUGF 1,'K : unknown keycode: %x\n',al
.normalnext2:
; 6. Advance to next key.
inc esi
cmp esi, 8
jb .normalloop
; 7. Save the packet data for future reference.
mov eax, dword [ebx+device_data.packet]
mov dword [ebx+keyboard_data.prevpacket], eax
mov eax, dword [ebx+device_data.packet+4]
mov dword [ebx+keyboard_data.prevpacket+4], eax
pop ebx esi ; restore registers to be stdcall
.next:
; 8. Initiate transfer on the interrupt pipe.
mov eax, [esp+20]
push 1 ; flags for USBNormalTransferAsync
push eax ; userdata for USBNormalTransferAsync
add eax, device_data.packet
stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \
eax, dword [eax+device_data.packetsize-device_data.packet], \
keyboard_data_ready;, <userdata>, <flags>
; 9. Return.
.nothing:
ret 20
.error:
; An error has occured.
; 10. If an error is caused by the disconnect, do nothing, it is handled
; in DeviceDisconnected. Otherwise, say a message.
cmp eax, 16
jz @f
push esi
mov esi, errormsgkbd
call SysMsgBoardStr
pop esi
@@:
ret 20
 
; Auxiliary procedure for keyboard_data_ready.
haskey:
movi edx, 2
@@:
cmp byte [ecx+edx], al
jz @f
inc edx
cmp edx, 7
jbe @b
@@:
ret
 
; Timer function for auto-repeat.
autorepeat_timer:
mov eax, [esp+4]
movzx ecx, [eax+keyboard_data.repeatkey]
test cl, cl
jns @f
push ecx
mov ecx, 0xE0
call SetKeyboardData
pop ecx
and cl, not 0x80
@@:
call SetKeyboardData
ret 4
 
; This function is called to update LED state on the keyboard.
SetKeyboardLights:
mov eax, [esp+4]
add eax, device_data.control
mov dword [eax], 21h + (9 shl 8) + (2 shl 24)
; class request to interface + SET_REPORT + Output zero report
mov byte [eax+6], 1
mov edx, [esp+8]
shr dl, 1
jnc @f
or dl, 4
@@:
lea ecx, [eax+keyboard_data.ledstate-device_data.control]
mov [ecx], dl
stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \
eax, ecx, 1, keyboard_data_ready.nothing, 0, 0
ret 8
 
; This function is called when it is safe to free keyboard data.
CloseKeyboard:
mov eax, [esp+4]
push ebx
call Kfree
pop ebx
ret 4
 
; This function is called when SET_PROTOCOL command for mouse is done,
; either successful or unsuccessful.
mouse_configured:
; Check the status of the transfer and go to the corresponding label
; in the main handler.
cmp dword [esp+8], 0
jnz mouse_data_ready.error
mov eax, [esp+20]
add eax, device_data.packet
jmp mouse_data_ready.next
 
; This function is called when another interrupt packet arrives,
; processed either successfully or unsuccessfully.
; It should parse the packet and initiate another transfer with
; the same callback function.
mouse_data_ready:
; 1. Check the status of the transfer.
mov eax, [esp+8]
test eax, eax
jnz .error
mov edx, [esp+16]
; 2. Parse the packet.
; For boot protocol, USB mouse packet consists of at least 3 bytes.
; The first byte is state of mouse buttons, the next two bytes are
; x and y movements.
; Normal mice do not distinguish between boot protocol and report protocol;
; in this case, scroll data are also present. Advanced mice, however,
; support two different protocols, boot protocol is used for compatibility
; and does not contain extended buttons or scroll data.
mov eax, [esp+12] ; buffer
push eax
xor ecx, ecx
cmp edx, 4
jbe @f
movsx ecx, byte [eax+4]
@@:
push ecx
xor ecx, ecx
cmp edx, 3
jbe @f
movsx ecx, byte [eax+3]
neg ecx
@@:
push ecx
xor ecx, ecx
cmp edx, 2
jbe @f
movsx ecx, byte [eax+2]
neg ecx
@@:
push ecx
movsx ecx, byte [eax+1]
push ecx
movzx ecx, byte [eax]
push ecx
call SetMouseData
pop eax
.next:
; 3. Initiate transfer on the interrupt pipe.
stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \
eax, dword [eax+device_data.packetsize-device_data.packet], mouse_data_ready, eax, 1
; 4. Return.
ret 20
.error:
; An error has occured.
; 5. If an error is caused by the disconnect, do nothing, it is handled
; in DeviceDisconnected. Otherwise, say a message.
cmp eax, 16
jz @f
push esi
mov esi, errormsgmouse
call SysMsgBoardStr
pop esi
@@:
ret 20
 
; This function is called when the device is disconnected.
DeviceDisconnected:
push ebx ; save used register to be stdcall
; 1. Say a message. Use different messages for keyboards and mice.
mov ebx, [esp+4+4]
push esi
mov esi, disconnectmsgk
cmp byte [ebx+device_data.type], 1
jz @f
mov esi, disconnectmsgm
@@:
stdcall SysMsgBoardStr
pop esi
; 2. If device is keyboard, then we must unregister it as a keyboard and
; possibly stop the auto-repeat timer.
cmp byte [ebx+device_data.type], 1
jnz .nokbd
mov eax, [ebx+keyboard_data.timer]
test eax, eax
jz @f
stdcall CancelTimerHS, eax
@@:
mov ecx, [ebx+keyboard_data.handle]
jecxz .nokbd
stdcall DelKeyboard, ecx
; If keyboard is registered, then we should free data in CloseKeyboard, not here.
jmp .nothing
.nokbd:
; 3. Free the device data.
xchg eax, ebx
call Kfree
; 4. Return.
.nothing:
pop ebx ; restore used register to be stdcall
ret 4 ; purge one dword argument to be stdcall
 
; strings
my_driver db 'usbhid',0
errormsgmouse db 'K : USB transfer error, disabling mouse',10,0
errormsgkbd db 'K : USB transfer error, disabling keyboard',10,0
disconnectmsgm db 'K : USB mouse disconnected',10,0
disconnectmsgk db 'K : USB keyboard disconnected',10,0
 
; data for keyboard: correspondence between HID usage keys and PS/2 scancodes.
EX = 80h
label control_keys byte
db 1Dh, 2Ah, 38h, 5Bh+EX, 1Dh+EX, 36h, 38h+EX, 5Ch+EX
label normal_keys byte
db 00h, 00h, 00h, 00h, 1Eh, 30h, 2Eh, 20h, 12h, 21h, 22h, 23h, 17h, 24h, 25h, 26h ; 0x
db 32h, 31h, 18h, 19h, 10h, 13h, 1Fh, 14h, 16h, 2Fh, 11h, 2Dh, 15h, 2Ch, 02h, 03h ; 1x
db 04h, 05h, 06h, 07h, 08h, 09h, 0Ah, 0Bh, 1Ch, 01h, 0Eh, 0Fh, 39h, 0Ch, 0Dh, 1Ah ; 2x
db 1Bh, 2Bh, 2Bh, 27h, 28h, 29h, 33h, 34h, 35h, 3Ah, 3Bh, 3Ch, 3Dh, 3Eh, 3Fh, 40h ; 3x
db 41h, 42h, 43h, 44h, 57h, 58h,37h+EX,46h,0,52h+EX,47h+EX,49h+EX,53h+EX,4Fh+EX,51h+EX,4Dh+EX ; 4x
db 4Bh+EX,50h+EX,48h+EX,45h,35h+EX,37h,4Ah,4Eh,1Ch+EX,4Fh,50h,51h,4Bh,4Ch,4Dh,47h ; 5x
db 48h, 49h, 52h, 53h, 56h,5Dh+EX,5Eh+EX,59h,64h,65h,66h, 67h, 68h, 69h, 6Ah, 6Bh ; 6x
db 6Ch, 6Dh, 6Eh, 76h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h ; 7x
db 00h, 00h, 00h, 00h, 00h, 7Eh, 00h, 73h, 70h, 7Dh, 79h, 7Bh, 5Ch, 00h, 00h, 00h ; 8x
db 0F2h,0F1h,78h, 77h, 76h
normal_keys_number = $ - normal_keys
 
; Exported variable: kernel API version.
align 4
version dd 50005h
; Structure with callback functions.
usb_functions:
dd 12
dd AddDevice
dd DeviceDisconnected
 
; Structure with callback functions for keyboards.
usbkbd_functions:
dd 12
dd CloseKeyboard
dd SetKeyboardLights
 
; for DEBUGF macro
include_debug_strings
 
; for uninitialized data
section '.data' data readable writable align 16
/kernel/branches/Kolibri-acpi/drivers/usb/urb.inc
0,0 → 1,121
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2007-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
struc URB
{
.fd dd ?
.bk dd ?
.dev dd ? ; pointer to associated device
.pipe dd ? ; pipe information
.status dd ? ; non-ISO status
.transfer_flags dd ? ; URB_SHORT_NOT_OK | ...
.transfer_buffer dd ? ; associated data buffer
.transfer_dma dd ? ; dma addr for transfer_buffer
.transfer_buffer_length dd ? ; data buffer length
.actual_length dd ? ; actual transfer length
.setup_packet dd ? ; setup packet (control only)
.setup_dma dd ? ; dma addr for setup_packet
.start_frame dd ? ; start frame (ISO)
.number_of_packets dd ? ; number of ISO packets
.interval dd ? ; transfer interval
 
.error_count dd ? ; number of ISO errors
.context dd ? ; context for completion
.complete dd ? ; (in) completion routine
.iso_frame_desc:
}
 
virtual at 0
URB URB
end virtual
 
 
struc REQ ;usb request
{
.request_type db ?
.request db ?
.value dw ?
.index dw ?
.length dw ?
}
 
virtual at 0
REQ REQ
end virtual
 
align 4
proc usb_control_msg stdcall, dev:dword, pipe:dword, request:dword,\
requesttype:dword, value:dword, index:dword,\
data:dword, size:dword, timeout:dword
 
locals
req REQ
endl
 
lea eax, [req]
mov ecx, [request]
mov ebx, [requesttupe]
mov edx, [value]
mov esi, [index]
mov edi, [size]
 
mov [eax+REQ.request_type], bl
mov [eax+REQ.request], cl
mov [eax+REQ.value], dx
mov [eax+REQ.index], si
mov [eax+REQ.length], di
 
stdcall usb_internal_control_msg, [dev], [pipe], \
eax, [data], [size], [timeout]
 
ret
endp
 
 
; returns status (negative) or length (positive)
static int usb_internal_control_msg(struct usb_device *usb_dev,
unsigned int pipe,
struct usb_ctrlrequest *cmd,
void *data, int len, int timeout)
{
struct urb *urb;
int retv;
int length;
 
urb = usb_alloc_urb(0, GFP_NOIO);
if (!urb)
return -ENOMEM;
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
len, usb_api_blocking_completion, NULL);
 
retv = usb_start_wait_urb(urb, timeout, &length);
if (retv < 0)
return retv;
else
return length;
}
 
 
;void usb_fill_control_urb (struct urb *urb,
; struct usb_device *dev,
; unsigned int pipe,
; unsigned char *setup_packet,
; void *transfer_buffer,
; int buffer_length,
; usb_complete_t complete_fn,
; void *context)
;{
;
; urb->dev = dev;
; urb->pipe = pipe;
; urb->setup_packet = setup_packet;
; urb->transfer_buffer = transfer_buffer;
; urb->transfer_buffer_length = buffer_length;
; urb->complete = complete_fn;
; urb->context = context;
;}
;
/kernel/branches/Kolibri-acpi/drivers/usb/usb.asm
0,0 → 1,435
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;driver sceletone
 
format MS COFF
 
API_VERSION equ 0 ;debug
 
include '../proc32.inc'
include '../imports.inc'
include 'urb.inc'
 
struc UHCI
{
.bus dd ?
.devfn dd ?
.io_base dd ?
.mm_base dd ?
.irq dd ?
.flags dd ?
.reset dd ?
.start dd ?
.stop dd ?
 
.port_c_suspend dd ?
.resuming_ports dd ?
.rh_state dd ?
.rh_numports dd ?
.is_stopped dd ?
.dead dd ?
 
.sizeof:
}
 
virtual at 0
UHCI UHCI
end virtual
 
struc IOCTL
{ .handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
 
virtual at 0
IOCTL IOCTL
end virtual
 
struc TD ;transfer descriptor
{
.link dd ?
.status dd ?
.token dd ?
.buffer dd ?
 
.addr dd ?
.frame dd ?
.fd dd ?
.bk dd ?
.sizeof:
}
 
virtual at 0
TD TD
end virtual
 
public START
public service_proc
public version
 
DEBUG equ 1
 
DRV_ENTRY equ 1
DRV_EXIT equ -1
STRIDE equ 4 ;size of row in devices table
 
SRV_GETVERSION equ 0
 
section '.flat' code readable align 16
 
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
.entry:
 
if DEBUG
mov esi, msgInit
call SysMsgBoardStr
end if
 
call init
 
stdcall RegService, my_service, service_proc
ret
.fail:
.exit:
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov ebx, [ioctl]
mov eax, [ebx+io_code]
cmp eax, SRV_GETVERSION
jne @F
 
mov eax, [ebx+output]
cmp [ebx+out_size], 4
jne .fail
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc detect
locals
last_bus dd ?
bus dd ?
devfn dd ?
endl
 
xor eax, eax
mov [bus], eax
inc eax
call PciApi
cmp eax, -1
je .err
 
mov [last_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
stdcall PciRead32, [bus], [devfn], dword 0
test eax, eax
jz .next
cmp eax, -1
je .next
 
mov edi, devices
@@:
mov ebx, [edi]
test ebx, ebx
jz .next
 
cmp eax, ebx
je .found
 
add edi, STRIDE
jmp @B
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
xor eax, eax
ret
.found:
mov eax, UHCI.sizeof
call Kmalloc
test eax, eax
jz .mem_fail
 
mov ebx, [bus]
mov [eax+UHCI.bus], ebx
 
mov ecx, [devfn]
mov [eax+UHCI.devfn], ecx
ret
.mem_fail:
if DEBUG
mov esi, msgMemFail
call SysMsgBoardStr
end if
.err:
xor eax, eax
ret
endp
 
PCI_BASE equ 0x20
USB_LEGKEY equ 0xC0
 
align 4
proc init
locals
uhci dd ?
endl
 
call detect
test eax, eax
jz .fail
 
mov [uhci], eax
 
stdcall PciRead32, [eax+UHCI.bus], [eax+UHCI.devfn], PCI_BASE
and eax, 0xFFC0
mov esi, [uhci]
mov [esi+UHCI.io_base], eax
 
stdcall uhci_reset, esi
 
stdcall finish_reset, [uhci]
 
.fail:
if DEBUG
mov esi, msgDevNotFound
call SysMsgBoardStr
end if
ret
endp
 
UHCI_USBINTR equ 4 ; interrupt register
 
UHCI_USBLEGSUP_RWC equ 0x8f00 ; the R/WC bits
UHCI_USBLEGSUP_RO equ 0x5040 ; R/O and reserved bits
 
UHCI_USBCMD_RUN equ 0x0001 ; RUN/STOP bit
UHCI_USBCMD_HCRESET equ 0x0002 ; Host Controller reset
UHCI_USBCMD_EGSM equ 0x0008 ; Global Suspend Mode
UHCI_USBCMD_CONFIGURE equ 0x0040 ; Config Flag
UHCI_USBINTR_RESUME equ 0x0002 ; Resume interrupt enable
 
PORTSC0 equ 0x10
PORTSC1 equ 0x12
 
 
UHCI_RH_RESET equ 0
UHCI_RH_SUSPENDED equ 1
UHCI_RH_AUTO_STOPPED equ 2
UHCI_RH_RESUMING equ 3
 
; In this state the HC changes from running to halted
; so it can legally appear either way.
UHCI_RH_SUSPENDING equ 4
 
; In the following states it's an error if the HC is halted.
; These two must come last.
UHCI_RH_RUNNING equ 5 ; The normal state
UHCI_RH_RUNNING_NODEVS equ 6 ; Running with no devices
 
UHCI_IS_STOPPED equ 9999
 
align 4
proc uhci_reset stdcall, uhci:dword
mov esi, [uhci]
stdcall PciRead16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY
test eax, not (UHCI_USBLEGSUP_RO or UHCI_USBLEGSUP_RWC)
jnz .reset
 
mov edx, [esi+UHCI.io_base]
in ax, dx
test ax, UHCI_USBCMD_RUN
jnz .reset
 
test ax, UHCI_USBCMD_CONFIGURE
jz .reset
 
test ax, UHCI_USBCMD_EGSM
jz .reset
 
add edx, UHCI_USBINTR
in ax, dx
test ax, not UHCI_USBINTR_RESUME
jnz .reset
ret
.reset:
stdcall PciWrite16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY, UHCI_USBLEGSUP_RWC
 
mov edx, [esi+UHCI.io_base]
mov ax, UHCI_USBCMD_HCRESET
out dx, ax
 
xor eax, eax
out dx, ax
add edx, UHCI_USBINTR
out dx, ax
ret
endp
 
proc finish_reset stdcall, uhci:dword
 
mov esi, [uhci]
mov edx, [esi+UHCI.io_base]
add edx, PORTSC0
xor eax, eax
out dx, ax
add edx, (PORTSC1-PORTSC0)
out dx, ax
 
mov [esi+UHCI.port_c_suspend], eax
mov [esi+UHCI.resuming_ports], eax
mov [esi+UHCI.rh_state], UHCI_RH_RESET
mov [esi+UHCI.rh_numports], 2
 
mov [esi+UHCI.is_stopped], UHCI_IS_STOPPED
; mov [ uhci_to_hcd(uhci)->state = HC_STATE_HALT;
; uhci_to_hcd(uhci)->poll_rh = 0;
 
mov [esi+UHCI.dead], eax ; Full reset resurrects the controller
 
ret
endp
 
proc insert_td stdcall, td:dword, frame:dword
 
mov edi, [td]
mov eax, [frame]
and eax, -1024
mov [edi+TD.frame], eax
 
mov ebx, [framelist]
mov edx, [dma_framelist]
shl eax, 5
 
mov ecx, [eax+ebx]
test ecx, ecx
jz .empty
 
mov ecx, [ecx+TD.bk] ;last TD
 
mov edx, [ecx+TD.fd]
mov [edi+TD.fd], edx
mov [edi+TD.bk], ecx
mov [ecx+TD.fd], edi
mov [edx+TD.bk], edi
 
mov eax, [ecx+TD.link]
mov [edi+TD.link], eax
mov ebx, [edi+TD.addr]
mov [ecx+TD.link], ebx
ret
.empty:
mov ecx, [eax+edx]
mov [edi+TD.link], ecx
mov [ebx+eax], edi
mov ecx, [edi+TD.addr]
mov [eax+edx], ecx
ret
endp
 
 
align 4
proc usb_get_descriptor stdcall, dev:dword, type:dword, index:dword,\
buf:dword, size:dword
 
locals
count dd ?
endl
 
mov esi, [buf]
mov ecx, [size]
xor eax, eax
cld
rep stosb
 
mov [count], 3
@@:
mov eax, [type]
shl eax, 8
add eax, [index]
stdcall usb_control_msg, [dev], pipe, USB_REQ_GET_DESCRIPTOR, \
USB_DIR_IN, eax,0,[buf], [size],\
USB_CTRL_GET_TIMEOUT
test eax, eax
jz .next
cmp eax, -1
je .next
jmp. ok
.next:
dec [count]
jnz @B
mov eax, -1
.ok:
ret
endp
 
DEVICE_ID equ 0x24D2 ; pci device id
VENDOR_ID equ 0x8086 ; device vendor id
QEMU_USB equ 0x7020
 
;all initialized data place here
 
align 4
devices dd (DEVICE_ID shl 16)+VENDOR_ID
dd (QEMU_USB shl 16)+VENDOR_ID
dd 0 ;terminator
 
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
 
my_service db 'UHCI',0 ;max 16 chars include zero
 
msgInit db 'detect hardware...',13,10,0
msgPCI db 'PCI accsess not supported',13,10,0
msgDevNotFound db 'device not found',13,10,0
msgMemFail db 'Kmalloc failed', 10,10,0
;msgFail db 'device not found',13,10,0
 
section '.data' data readable writable align 16
 
;all uninitialized data place here
 
/kernel/branches/Kolibri-acpi/drivers/usb
Property changes:
Added: svn:ignore
+*.mnt
+lang.inc
+*.bat
+out.txt
+scin*
+*.obj
/kernel/branches/Kolibri-acpi/fs/fat.inc
File deleted
/kernel/branches/Kolibri-acpi/fs/fs-et.inc
0,0 → 1,12
dir0:
db 'KÕVAKETAS '
db 'MÄLUKETAS '
db 'FLOPPIKETAS'
db 0
 
dir1:
db 'ESIMENE '
db 'TEINE '
db 'KOLAMS '
db 'NELJAS '
db 0
/kernel/branches/Kolibri-acpi/fs/fs.inc
0,0 → 1,682
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; System service for filesystem call ;;
;; (C) 2004 Ville Turjanmaa, License: GPL ;;
;; 29.04.2006 Elimination of hangup after the ;;
;; expiration hd_wait_timeout (for LBA) - Mario79 ;;
;; 15.01.2005 get file size/attr/date, ;;
;; file_append (only for hd) - ATV ;;
;; 23.11.2004 test if hd/partition is set - ATV ;;
;; 18.11.2004 get_disk_info and more error codes - ATV ;;
;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;;
;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
iglobal
 
if lang eq sp
include 'fs/fs-sp.inc'
else if lang eq et
include 'fs/fs-et.inc'
else
dir0:
db 'HARDDISK '
db 'RAMDISK '
db 'FLOPPYDISK '
db 0
 
dir1:
db 'FIRST '
db 'SECOND '
db 'THIRD '
db 'FOURTH '
db 0
end if
 
not_select_IDE db 0
 
hd_address_table:
dd 0x1f0,0x00,0x1f0,0x10
dd 0x170,0x00,0x170,0x10
endg
 
file_system:
 
; IN:
;
; eax = 0 ; read file /RamDisk/First 6
; eax = 8 ; lba read
; eax = 15 ; get_disk_info
;
; OUT:
;
; eax = 0 : read ok
; eax = 1 : no hd base and/or partition defined
; eax = 2 : function is unsupported for this FS
; eax = 3 : unknown FS
; eax = 4 : partition not defined at hd
; eax = 5 : file not found
; eax = 6 : end of file
; eax = 7 : memory pointer not in application area
; eax = 8 : disk full
; eax = 9 : fat table corrupted
; eax = 10 : access denied
; eax = 11 : disk error
;
; ebx = size
 
; \begin{diamond}[18.03.2006]
; for subfunction 16 (start application) error codes must be negative
; because positive values are valid PIDs
; so possible return values are:
; eax > 0 : process created, eax=PID
 
; -0x10 <= eax < 0 : -eax is filesystem error code:
; eax = -1 = 0xFFFFFFFF : no hd base and/or partition defined
; eax = -3 = 0xFFFFFFFD : unknown FS
; eax = -5 = 0xFFFFFFFB : file not found
; eax = -6 = 0xFFFFFFFA : unexpected end of file (probably not executable file)
; eax = -9 = 0xFFFFFFF7 : fat table corrupted
; eax = -10 = 0xFFFFFFF6 : access denied
 
; -0x20 <= eax < -0x10: eax is process creation error code:
; eax = -0x20 = 0xFFFFFFE0 : too many processes
; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable
; eax = -0x1E = 0xFFFFFFE2 : no memory
 
; ebx is not changed
 
; \end{diamond}[18.03.2006]
 
; Extract parameters
; add eax, std_application_base_address ; abs start of info block
 
cmp dword [eax+0], 15; GET_DISK_INFO
je fs_info
 
cmp dword [CURRENT_TASK], 1; no memory checks for kernel requests
jz no_checks_for_kernel
mov edx, eax
cmp dword [eax+0], 1
jnz .usual_check
mov ebx, [eax+12]
; add ebx,std_application_base_address
mov ecx, [eax+8]
call check_region
test eax, eax
jnz area_in_app_mem
 
.error_output:
mov esi, buffer_failed
call sys_msg_board_str
; mov eax,7
mov dword [esp+36], 7
ret
iglobal
buffer_failed db 'K : Buffer check failed',13,10,0
endg
.usual_check:
cmp dword [eax+0], 0
mov ecx, 512
jnz .small_size
mov ecx, [eax+8]
shl ecx, 9
.small_size:
mov ebx, [eax+12]
; add ebx,std_application_base_address
call check_region
test eax, eax
jz .error_output
area_in_app_mem:
mov eax, edx
no_checks_for_kernel:
 
fs_read:
 
mov ebx, [eax+20] ; program wants root directory ?
test bl, bl
je fs_getroot
test bh, bh
jne fs_noroot
fs_getroot:
; \begin{diamond}[18.03.2006]
; root - only read is allowed
; other operations return "access denied", eax=10
; (execute operation returns eax=-10)
cmp dword [eax], 0
jz .read_root
mov dword [esp+36], 10
ret
.read_root:
; \end{diamond}[18.03.2006]
mov esi, dir0
mov edi, [eax+12]
; add edi,std_application_base_address
mov ecx, 11
push ecx
; cld ; already is
rep movsb
mov al, 0x10
stosb
add edi, 32-11-1
pop ecx
rep movsb
stosb
and dword [esp+36], 0; ok read
mov dword [esp+24], 32*2; size of root
ret
 
fs_info: ;start of code - Mihasik
push eax
cmp [eax+21], byte 'r'
je fs_info_r
cmp [eax+21], byte 'R'
je fs_info_r
mov eax, 3 ;if unknown disk
xor ebx, ebx
xor ecx, ecx
xor edx, edx
jmp fs_info1
fs_info_r:
call ramdisk_free_space;if ramdisk
mov ecx, edi ;free space in ecx
shr ecx, 9 ;free clusters
mov ebx, 2847 ;total clusters
mov edx, 512 ;cluster size
xor eax, eax ;always 0
fs_info1:
pop edi
mov [esp+36], eax
mov [esp+24], ebx ; total clusters on disk
mov [esp+32], ecx ; free clusters on disk
mov [edi], edx ; cluster size in bytes
ret ;end of code - Mihasik
 
fs_noroot:
 
push dword [eax+0] ; read/write/delete/.../makedir/rename/lba/run
push dword [eax+4] ; 512 block number to read
push dword [eax+8] ; bytes to write/append or 512 blocks to read
mov ebx, [eax+12]
; add ebx,std_application_base_address
push ebx ; abs start of return/save area
 
lea esi, [eax+20] ; abs start of dir + filename
mov edi, [eax+16]
; add edi,std_application_base_address ; abs start of work area
 
call expand_pathz
 
push edi ; dir start
push ebx ; name of file start
 
mov eax, [edi+1]
cmp eax, 'RD '
je fs_yesramdisk
cmp eax, 'RAMD'
jne fs_noramdisk
 
fs_yesramdisk:
 
cmp byte [edi+1+11], 0
je fs_give_dir1
 
mov eax, [edi+1+12]
cmp eax, '1 '
je fs_yesramdisk_first
cmp eax, 'FIRS'
jne fs_noramdisk
 
fs_yesramdisk_first:
 
cmp dword [esp+20], 8; LBA read ramdisk
jne fs_no_LBA_read_ramdisk
 
mov eax, [esp+16] ; LBA block to read
mov ecx, [esp+8] ; abs pointer to return area
 
call LBA_read_ramdisk
jmp file_system_return
 
 
fs_no_LBA_read_ramdisk:
 
cmp dword [esp+20], 0; READ
jne fs_noramdisk_read
 
mov eax, [esp+4] ; fname
add eax, 2*12+1
mov ebx, [esp+16] ; block start
inc ebx
mov ecx, [esp+12] ; block count
mov edx, [esp+8] ; return
mov esi, [esp+0]
sub esi, eax
add esi, 12+1 ; file name length
call fileread
 
jmp file_system_return
 
 
fs_noramdisk_read:
fs_noramdisk:
 
;********************************************************************
mov eax, [edi+1]
cmp eax, 'FD '
je fs_yesflpdisk
cmp eax, 'FLOP'
jne fs_noflpdisk
 
fs_yesflpdisk:
call reserve_flp
 
cmp byte [edi+1+11], 0
je fs_give_dir1
 
mov eax, [edi+1+12]
cmp eax, '1 '
je fs_yesflpdisk_first
cmp eax, 'FIRS'
je fs_yesflpdisk_first
cmp eax, '2 '
je fs_yesflpdisk_second
cmp eax, 'SECO'
jne fs_noflpdisk
jmp fs_yesflpdisk_second
 
fs_yesflpdisk_first:
mov [flp_number], 1
jmp fs_yesflpdisk_start
fs_yesflpdisk_second:
mov [flp_number], 2
fs_yesflpdisk_start:
cmp dword [esp+20], 0; READ
jne fs_noflpdisk_read
 
mov eax, [esp+4] ; fname
add eax, 2*12+1
mov ebx, [esp+16] ; block start
inc ebx
mov ecx, [esp+12] ; block count
mov edx, [esp+8] ; return
mov esi, [esp+0]
sub esi, eax
add esi, 12+1 ; file name length
call floppy_fileread
 
jmp file_system_return
 
 
fs_noflpdisk_read:
fs_noflpdisk:
;*****************************************************************
 
old_path_harddisk:
mov eax, [edi+1]
cmp eax, 'HD '
je fs_yesharddisk
cmp eax, 'HARD'
jne fs_noharddisk
 
fs_yesharddisk:
cmp dword [esp+20], 8; LBA read
jne fs_no_LBA_read
mov eax, [esp+16] ; LBA block to read
lea ebx, [edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH
mov ecx, [esp+8] ; abs pointer to return area
call LBA_read
jmp file_system_return
 
fs_no_LBA_read:
 
hd_err_return:
 
fs_noharddisk:
; \begin{diamond}[18.03.2006]
mov eax, 5 ; file not found
; а может быть, возвращать другой код ошибки?
mov ebx, [esp+24+24]; do not change ebx in application
; \end{diamond}[18.03.2006]
 
file_system_return:
 
add esp, 24
 
mov [esp+36], eax
mov [esp+24], ebx
ret
 
 
fs_give_dir1:
 
; \begin{diamond}[18.03.2006]
; /RD,/FD,/HD - only read is allowed
; other operations return "access denied", eax=10
; (execute operation returns eax=-10)
cmp dword [esp+20], 0
jz .read
add esp, 20
pop ecx
mov dword [esp+36], 10
ret
.read:
; \end{diamond}[18.03.2006]
mov al, 0x10
mov ebx, 1
mov edi, [esp+8]
mov esi, dir1
fs_d1_new:
mov ecx, 11
; cld
rep movsb
stosb
add edi, 32-11-1
dec ebx
jne fs_d1_new
 
add esp, 24
 
and dword [esp+36], 0; ok read
mov dword [esp+24], 32*1; dir/data size
ret
 
 
 
LBA_read_ramdisk:
 
cmp [lba_read_enabled], 1
je lbarrl1
 
xor ebx, ebx
mov eax, 2
ret
 
lbarrl1:
 
cmp eax, 18*2*80
jb lbarrl2
xor ebx, ebx
mov eax, 3
ret
 
lbarrl2:
 
pushad
 
call restorefatchain
 
mov edi, ecx
mov esi, eax
 
shl esi, 9
add esi, RAMDISK
mov ecx, 512/4
; cld
rep movsd
 
popad
 
xor ebx, ebx
xor eax, eax
ret
 
LBA_read:
 
; IN:
;
; eax = LBA block to read
; ebx = pointer to FIRST/SECOND/THIRD/FOURTH
; ecx = abs pointer to return area
 
cmp [lba_read_enabled], 1
je lbarl1
mov eax, 2
ret
 
lbarl1:
 
pushad
mov ecx, ide_mutex
call mutex_lock
popad
 
push eax
push ecx
 
mov edi, hd_address_table
mov esi, dir1
mov eax, [ebx]
mov edx, '1 '
mov ecx, 4
blar0:
cmp eax, [esi]
je blar2
cmp eax, edx
je blar2
inc edx
add edi, 8
add esi, 11
dec ecx
jnz blar0
 
mov eax, 1
mov ebx, 1
jmp LBA_read_ret
 
blar2:
mov eax, [edi+0]
mov ebx, [edi+4]
 
mov [hdbase], eax
mov [hdid], ebx
 
call wait_for_hd_idle
cmp [hd_error], 0
jne hd_lba_error
 
; eax = hd port
; ebx = set for primary (0x00) or slave (0x10)
 
cli
 
mov edx, eax
inc edx
xor eax, eax
out dx, al
inc edx
inc eax
out dx, al
inc edx
mov eax, [esp+4]
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
and al, 1+2+4+8
add al, bl
add al, 128+64+32
out dx, al
 
inc edx
mov al, 20h
out dx, al
 
sti
 
call wait_for_sector_buffer
cmp [hd_error], 0
jne hd_lba_error
 
cli
 
mov edi, [esp+0]
mov ecx, 256
sub edx, 7
cld
rep insw
 
sti
 
xor eax, eax
xor ebx, ebx
 
LBA_read_ret:
mov [hd_error], 0
mov [hd1_status], 0
add esp, 2*4
pushad
mov ecx, ide_mutex
call mutex_unlock
popad
 
ret
 
 
expand_pathz:
; IN:
; esi = asciiz path & file
; edi = buffer for path & file name
; OUT:
; edi = directory & file : / 11 + / 11 + / 11 - zero terminated
; ebx = /file name - zero terminated
; esi = pointer after source
 
push eax
push ecx
push edi;[esp+0]
 
pathz_start:
mov byte [edi], '/'
inc edi
mov al, 32
mov ecx, 11
cld
rep stosb ; clear filename area
sub edi, 11
mov ebx, edi ; start of dir/file name
 
pathz_new_char:
mov al, [esi]
inc esi
cmp al, 0
je pathz_end
 
cmp al, '/'
jne pathz_not_path
cmp edi, ebx ; skip first '/'
jz pathz_new_char
lea edi, [ebx+11] ; start of next directory
jmp pathz_start
 
pathz_not_path:
cmp al, '.'
jne pathz_not_ext
lea edi, [ebx+8] ; start of extension
jmp pathz_new_char
 
pathz_not_ext:
cmp al, 'a'
jb pathz_not_low
cmp al, 'z'
ja pathz_not_low
sub al, 0x20 ; char to uppercase
 
pathz_not_low:
mov [edi], al
inc edi
mov eax, [esp+0] ; start_of_dest_path
add eax, 512 ; keep maximum path under 512 bytes
cmp edi, eax
jb pathz_new_char
 
pathz_end:
cmp ebx, edi ; if path end with '/'
jnz pathz_put_zero ; go back 1 level
sub ebx, 12
 
pathz_put_zero:
mov byte [ebx+11], 0
dec ebx ; include '/' char into file name
pop edi
pop ecx
pop eax
ret
 
;*******************************************
;* string to number
;* input eax - 4 byte string
;* output eax - number
;*******************************************
StringToNumber:
; ПЕРЕВОД СТРОКОВОГО ЧИСЛА В ЧИСЛОВОЙ ВИД
; Вход:
; EDI - адрес строки с числом. Конец числа отмечен кодом 0Dh
; Выход:
; CF - индикатор ошибок:
; 0 - ошибок нет;
; 1 - ошибка
; Если CF=0, то AX - число.
 
push bx
push cx
push dx
push edi
mov [partition_string], eax
mov edi, partition_string
xor cx, cx
i1:
mov al, [edi]
cmp al, 32;13
je i_exit
; cmp al,'0'
; jb err
; cmp al,'9'
; ja err
sub al, 48
shl cx, 1
jc error
mov bx, cx
shl cx, 1
jc error
shl cx, 1
jc error
add cx, bx
jc error
cbw
add cx, ax
jc error
i3:
inc edi
jmp i1
i_exit:
mov ax, cx
clc
i4:
movzx eax, ax
pop edi
pop dx
pop cx
pop bx
ret
 
error:
stc
jmp i4
 
partition_string:
dd 0
db 32
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/fs/fat12.inc
0,0 → 1,2268
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FAT12.INC ;;
;; (C) 2005 Mario79, License: GPL ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
n_sector dd 0 ; temporary save for sector value
flp_status dd 0
clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write
path_pointer_flp dd 0
pointer_file_name_flp dd 0
save_root_flag db 0
save_flag db 0
root_read db 0 ; 0-necessary to load root, 1-not to load root
flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat
flp_number db 0 ; 1- Floppy A, 2-Floppy B
old_track db 0 ; old value track
flp_label rb 15 ; Label and ID of inserted floppy disk
 
reserve_flp:
 
cli
cmp [flp_status], 0
je reserve_flp_ok
 
sti
call change_task
jmp reserve_flp
 
reserve_flp_ok:
 
push eax
mov eax, [CURRENT_TASK]
shl eax, 5
mov eax, [eax+CURRENT_TASK+TASKDATA.pid]
mov [flp_status], eax
pop eax
sti
ret
 
 
floppy_fileread:
;----------------------------------------------------------------
;
; fileread - sys floppy
;
; eax points to filename 11 chars - for root directory
; ebx first wanted block ; 1+ ; if 0 then set to 1
; ecx number of blocks to read ; 1+ ; if 0 then set to 1
; edx mem location to return data
; esi length of filename 12*X
; edi pointer to path /fd/1/...... - for all files in nested directories
;
; ret ebx = size or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
; 10 = access denied
;--------------------------------------------------------------
 
mov [save_flag], 0
mov [path_pointer_flp], edi
test esi, esi ; return ramdisk root
jnz fr_noroot_1
cmp ebx, 224/16
jbe fr_do_1
mov eax, 5
xor ebx, ebx
mov [flp_status], ebx
ret
 
fr_do_1:
push ebx ecx edx
call read_flp_root
pop edx ecx ebx
cmp [FDC_Status], 0
jne fdc_status_error_1
mov edi, edx
dec ebx
shl ebx, 9
mov esi, FLOPPY_BUFF
add esi, ebx
shl ecx, 9
cld
rep movsb
xor eax, eax
xor ebx, ebx
; mov eax,0 ; ok read
; mov ebx,0
mov [flp_status], eax
ret
fdc_status_error_1:
xor eax, eax
mov [flp_status], eax
mov eax, 10
or ebx, -1
ret
 
fr_noroot_1:
sub esp, 32
call expand_filename
frfloppy_1:
test ebx, ebx
jnz frfl5_1
mov ebx, 1
frfl5_1:
test ecx, ecx
jnz frfl6_1
mov ecx, 1
frfl6_1:
dec ebx
push eax
push eax ebx ecx edx esi edi
call read_flp_fat
cmp [FDC_Status], 0
jne fdc_status_error_3_1
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 1; Сторона
mov [FDD_Sector], 2; Сектор
call SeekTrack
mov dh, 14
l.20_1:
call ReadSectWithRetr
cmp [FDC_Status], 0
jne fdc_status_error_3_1
mov dl, 16
mov edi, FDD_BUFF
inc [FDD_Sector]
l.21_1:
mov esi, eax ;Name of file we want
mov ecx, 11
cld
rep cmpsb ;Found the file?
je fifound_1 ;Yes
add ecx, 21
add edi, ecx ;Advance to next entry
dec dl
test dl, dl
jnz l.21_1
dec dh
test dh, dh
jnz l.20_1
fdc_status_error_3:
mov eax, 5 ; file not found ?
or ebx, -1
add esp, 32+28
mov [flp_status], 0
ret
fdc_status_error_3_2:
cmp [FDC_Status], 0
je fdc_status_error_3
fdc_status_error_3_1:
add esp, 32+28
jmp fdc_status_error_1
 
fifound_1:
mov eax, [path_pointer_flp]
cmp [eax+36], byte 0
je fifound_2
add edi, 0xf
mov eax, [edi]
and eax, 65535
mov ebx, [path_pointer_flp]
add ebx, 36
call get_cluster_of_a_path_flp
jc fdc_status_error_3_2
mov ebx, [ebx-11+28] ;file size
mov [esp+20], ebx
mov [esp+24], ebx
jmp fifound_3
fifound_2:
mov ebx, [edi-11+28] ;file size
mov [esp+20], ebx
mov [esp+24], ebx
add edi, 0xf
mov eax, [edi]
fifound_3:
and eax, 65535
mov [n_sector], eax ;eax=cluster
frnew_1:
add eax, 31 ;bootsector+2*fat+filenames
cmp [esp+16], dword 0; wanted cluster ?
jne frfl7_1
call read_chs_sector
cmp [FDC_Status], 0
jne fdc_status_error_5
mov edi, [esp+8]
call give_back_application_data_1
add [esp+8], dword 512
dec dword [esp+12] ; last wanted cluster ?
cmp [esp+12], dword 0
je frnoread_1
jmp frfl8_1
frfl7_1:
dec dword [esp+16]
frfl8_1:
mov edi, [n_sector]
shl edi, 1 ;find next cluster from FAT
add edi, FLOPPY_FAT
mov eax, [edi]
and eax, 4095
mov edi, eax
mov [n_sector], edi
cmp edi, 4095 ;eof - cluster
jz frnoread2_1
cmp [esp+24], dword 512;eof - size
jb frnoread_1
sub [esp+24], dword 512
jmp frnew_1
 
read_chs_sector:
call calculate_chs
call ReadSectWithRetr
ret
 
frnoread2_1:
cmp [esp+16], dword 0; eof without read ?
je frnoread_1
 
pop edi esi edx ecx
add esp, 4
pop ebx; ebx <- eax : size of file
add esp, 36
mov eax, 6; end of file
mov [flp_status], 0
ret
 
frnoread_1:
pop edi esi edx ecx
add esp, 4
pop ebx; ebx <- eax : size of file
add esp, 36
xor eax, eax
mov [flp_status], eax
ret
 
fdc_status_error_5:
pop edi esi edx ecx
add esp, 4
pop ebx; ebx <- eax : size of file
add esp, 36
jmp fdc_status_error_1
 
read_flp_root:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_root_read
cmp [root_read], 1
je unnecessary_root_read
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 1; Сторона
mov [FDD_Sector], 2; Сектор
mov edi, FLOPPY_BUFF
call SeekTrack
read_flp_root_1:
call ReadSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_root_read
push edi
call give_back_application_data_1
pop edi
add edi, 512
inc [FDD_Sector]
cmp [FDD_Sector], 16
jne read_flp_root_1
mov [root_read], 1
unnecessary_root_read:
popa
ret
 
 
read_flp_fat:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_flp_fat
cmp [flp_fat], 1
je unnecessary_flp_fat
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 0; Сторона
mov [FDD_Sector], 2; Сектор
mov edi, FLOPPY_BUFF
call SeekTrack
read_flp_fat_1:
call ReadSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat
push edi
call give_back_application_data_1
pop edi
add edi, 512
inc [FDD_Sector]
cmp [FDD_Sector], 19
jne read_flp_fat_1
mov [FDD_Sector], 1
mov [FDD_Head], 1
call ReadSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat
call give_back_application_data_1
call calculatefatchain_flp
mov [root_read], 0
mov [flp_fat], 1
unnecessary_flp_fat:
popa
ret
 
calculatefatchain_flp:
pushad
 
mov esi, FLOPPY_BUFF
mov edi, FLOPPY_FAT
 
fcnew_1:
mov eax, dword [esi]
mov ebx, dword [esi+4]
mov ecx, dword [esi+8]
mov edx, ecx
shr edx, 4;8 ok
shr dx, 4;7 ok
xor ch, ch
shld ecx, ebx, 20;6 ok
shr cx, 4;5 ok
shld ebx, eax, 12
and ebx, 0x0fffffff;4 ok
shr bx, 4;3 ok
shl eax, 4
and eax, 0x0fffffff;2 ok
shr ax, 4;1 ok
mov dword [edi], eax
add edi, 4
mov dword [edi], ebx
add edi, 4
mov dword [edi], ecx
add edi, 4
mov dword [edi], edx
add edi, 4
add esi, 12
 
cmp edi, FLOPPY_FAT+2856*2;2849 clusters
jnz fcnew_1
 
popad
ret
 
check_label:
pushad
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 0; Сторона
mov [FDD_Sector], 1; Сектор
call FDDMotorON
call RecalibrateFDD
cmp [FDC_Status], 0
jne fdc_status_error
call SeekTrack
cmp [FDC_Status], 0
jne fdc_status_error
call ReadSectWithRetr
cmp [FDC_Status], 0
jne fdc_status_error
mov esi, flp_label
mov edi, FDD_BUFF+39
mov ecx, 15
cld
rep cmpsb
je same_label
mov [root_read], 0
mov [flp_fat], 0
same_label:
mov esi, FDD_BUFF+39
mov edi, flp_label
mov ecx, 15
cld
rep movsb
popad
ret
fdc_status_error:
popad
ret
 
save_flp_root:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_root_save
cmp [root_read], 0
je unnecessary_root_save
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 1; Сторона
mov [FDD_Sector], 2; Сектор
mov esi, FLOPPY_BUFF
call SeekTrack
save_flp_root_1:
push esi
call take_data_from_application_1
pop esi
add esi, 512
call WriteSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_root_save
inc [FDD_Sector]
cmp [FDD_Sector], 16
jne save_flp_root_1
unnecessary_root_save:
popa
ret
 
save_flp_fat:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_flp_fat_save
cmp [flp_fat], 0
je unnecessary_flp_fat_save
call restorefatchain_flp
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 0; Сторона
mov [FDD_Sector], 2; Сектор
mov esi, FLOPPY_BUFF
call SeekTrack
save_flp_fat_1:
push esi
call take_data_from_application_1
pop esi
add esi, 512
call WriteSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat_save
inc [FDD_Sector]
cmp [FDD_Sector], 19
jne save_flp_fat_1
mov [FDD_Sector], 1
mov [FDD_Head], 1
call take_data_from_application_1
call WriteSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat_save
mov [root_read], 0
unnecessary_flp_fat_save:
popa
ret
 
 
restorefatchain_flp: ; restore fat chain
pushad
 
mov esi, FLOPPY_FAT
mov edi, FLOPPY_BUFF
 
fcnew2_1:
mov eax, dword [esi]
mov ebx, dword [esi+4]
shl ax, 4
shl eax, 4
shl bx, 4
shr ebx, 4
shrd eax, ebx, 8
shr ebx, 8
mov dword [edi], eax
add edi, 4
mov word [edi], bx
add edi, 2
add esi, 8
 
cmp edi, FLOPPY_BUFF+0x1200;4274 bytes - all used FAT
jb fcnew2_1
 
mov esi, FLOPPY_BUFF ; duplicate fat chain
mov edi, FLOPPY_BUFF+0x1200
mov ecx, 0x1200/4
cld
rep movsd
 
popad
ret
 
 
save_chs_sector:
call calculate_chs
call WriteSectWithRetr
ret
 
calculate_chs:
mov bl, [FDD_Track]
mov [old_track], bl
mov ebx, 18
xor edx, edx
div ebx
inc edx
mov [FDD_Sector], dl
xor edx, edx
mov ebx, 2
div ebx
mov [FDD_Track], al
mov [FDD_Head], 0
test edx, edx
jz no_head_2
inc [FDD_Head]
no_head_2:
mov dl, [old_track]
cmp dl, [FDD_Track]
je no_seek_track_1
call SeekTrack
no_seek_track_1:
ret
 
 
get_cluster_of_a_path_flp:
;---------------------------------------------------------
; input : EBX = pointer to a path string
; (example: the path "/files/data/document" become
; "files......data.......document...0"
; '.' = space char
; '0' = char(0) (ASCII=0) !!! )
; output : if (CARRY=1) -> ERROR in the PATH
; if (CARRY=0) -> EAX=cluster
;---------------------------------------------------------
 
push edx
mov edx, ebx
 
search_end_of_path_flp:
cmp [save_flag], 0
jne search_end_of_path_flp_1
cmp byte [edx], 0
je found_end_of_path_flp
jmp search_end_of_path_flp_2
search_end_of_path_flp_1:
cmp byte [edx+12], 0
je found_end_of_path_flp
search_end_of_path_flp_2:
inc edx; '/'
call analyze_directory_flp
jc directory_not_found_flp
 
mov eax, [ebx+20-2] ; read the HIGH 16bit cluster field
mov ax, [ebx+26] ; read the LOW 16bit cluster field
and eax, 0xfff ;[fatMASK]
add edx, 11 ; 8+3 (name+extension)
jmp search_end_of_path_flp
 
found_end_of_path_flp:
inc edx
mov [pointer_file_name_flp], edx
pop edx
clc ; no errors
ret
 
directory_not_found_flp:
pop edx
stc ; errors occour
ret
 
analyze_directory_flp:
;--------------------------------
; input : EAX = first cluster of the directory
; EBX = pointer to filename
; output : IF CARRY=0 EAX = sector where th file is found
; EBX = pointer in buffer
; [buffer .. buffer+511]
; ECX,EDX,EDI,EDI not changed
; IF CARRY=1
;--------------------------------
push ebx;[esp+16]
push ecx
push edx
push esi
push edi
 
 
adr56_flp:
mov [clust_tmp_flp], eax
add eax, 31
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jne not_found_file_analyze_flp
 
mov ecx, 512/32
mov ebx, FDD_BUFF
 
adr1_analyze_flp:
mov esi, edx;[esp+16]
mov edi, ebx
cld
push ecx
mov ecx, 11
rep cmpsb
pop ecx
je found_file_analyze_flp
 
add ebx, 32
loop adr1_analyze_flp
 
mov eax, [clust_tmp_flp]
shl eax, 1 ;find next cluster from FAT
add eax, FLOPPY_FAT
mov eax, [eax]
and eax, 4095
cmp eax, 0x0ff8
jb adr56_flp
not_found_file_analyze_flp:
pop edi
pop esi
pop edx
pop ecx
add esp, 4
stc ;file not found
ret
 
found_file_analyze_flp:
pop edi
pop esi
pop edx
pop ecx
add esp, 4
clc ;file found
ret
 
 
; \begin{diamond}
fat_find_lfn:
; in: esi->name
; [esp+4] = next
; [esp+8] = first
; [esp+C]... - possibly parameters for first and next
; out: CF=1 - file not found, eax=error code
; else CF=0, esi->next name component, edi->direntry
pusha
lea eax, [esp+0Ch+20h]
call dword [eax-4]
jc .reterr
sub esp, 262*2 ; reserve place for LFN
push 0 ; for fat_get_name: read ASCII name
.l1:
lea ebp, [esp+4]
call fat_get_name
jc .l2
call fat_compare_name
jz .found
.l2:
mov ebp, [esp+8+262*2+4]
lea eax, [esp+0Ch+20h+262*2+4]
call dword [eax-8]
jnc .l1
add esp, 262*2+4
.reterr:
mov [esp+28], eax
stc
popa
ret
.found:
add esp, 262*2+4
mov ebp, [esp+8]
; if this is LFN entry, advance to true entry
cmp byte [edi+11], 0xF
jnz @f
lea eax, [esp+0Ch+20h]
call dword [eax-8]
jc .reterr
@@:
add esp, 8 ; CF=0
push esi
push edi
popa
ret
 
uglobal
; this is for delete support
fd_prev_sector dd ?
fd_prev_prev_sector dd ?
endg
 
flp_root_next:
cmp edi, OS_BASE+0xD200-0x20
jae @f
add edi, 0x20
ret ; CF=0
@@:
; read next sector
inc dword [eax]
cmp dword [eax], 14
jae flp_root_first.readerr
push [fd_prev_sector]
pop [fd_prev_prev_sector]
push eax
mov eax, [eax]
add eax, 19-1
mov [fd_prev_sector], eax
pop eax
flp_root_first:
mov eax, [eax]
pusha
add eax, 19
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .readerr
mov edi, FDD_BUFF
ret ; CF=0
.readerr:
stc
ret
 
flp_rootmem_first:
mov edi, FLOPPY_BUFF
clc
ret
flp_rootmem_next:
add edi, 0x20
cmp edi, FLOPPY_BUFF+14*0x200
cmc
flp_rootmem_next_write:
flp_rootmem_begin_write:
flp_rootmem_end_write:
ret
flp_rootmem_extend_dir:
stc
ret
 
flp_notroot_next:
cmp edi, OS_BASE+0xD200-0x20
jae flp_notroot_next_sector
add edi, 0x20
ret ; CF=0
flp_notroot_next_sector:
push ecx
mov ecx, [eax]
push [fd_prev_sector]
pop [fd_prev_prev_sector]
add ecx, 31
mov [fd_prev_sector], ecx
mov ecx, [(ecx-31)*2+FLOPPY_FAT]
and ecx, 0xFFF
cmp ecx, 2849
jae flp_notroot_first.err2
mov [eax], ecx
pop ecx
flp_notroot_first:
mov eax, [eax]
cmp eax, 2
jb .err
cmp eax, 2849
jae .err
pusha
add eax, 31
call read_chs_sector
popa
mov edi, FDD_BUFF
cmp [FDC_Status], 0
jnz .err
ret ; CF=0
.err2:
pop ecx
.err:
stc
ret
flp_notroot_begin_write:
pusha
mov eax, [eax]
add eax, 31
call read_chs_sector
popa
ret
flp_notroot_end_write:
pusha
mov eax, [eax]
add eax, 31
call save_chs_sector
popa
ret
flp_notroot_next_write:
cmp edi, OS_BASE+0xD200
jae @f
ret
@@:
call flp_notroot_end_write
jmp flp_notroot_next_sector
flp_notroot_extend_dir:
; find free cluster in FAT
pusha
xor eax, eax
mov edi, FLOPPY_FAT
mov ecx, 2849
repnz scasw
jnz .notfound
mov word [edi-2], 0xFFF ; mark as last cluster
sub edi, FLOPPY_FAT
shr edi, 1
dec edi
mov eax, [esp+28]
mov ecx, [eax]
mov [FLOPPY_FAT+ecx*2], di
mov [eax], edi
xor eax, eax
mov edi, FDD_BUFF
mov ecx, 128
rep stosd
popa
call flp_notroot_end_write
mov edi, FDD_BUFF
clc
ret
.notfound:
popa
stc
ret
 
fd_find_lfn:
; in: esi+ebp -> name
; out: CF=1 - file not found
; else CF=0 and edi->direntry, eax=directory cluster (0 for root)
push esi edi
push 0
push flp_root_first
push flp_root_next
.loop:
call fat_find_lfn
jc .notfound
cmp byte [esi], 0
jz .found
.continue:
test byte [edi+11], 10h
jz .notfound
movzx eax, word [edi+26] ; cluster
mov [esp+8], eax
mov dword [esp+4], flp_notroot_first
mov dword [esp], flp_notroot_next
jmp .loop
.notfound:
add esp, 12
pop edi esi
stc
ret
.found:
test ebp, ebp
jz @f
mov esi, ebp
xor ebp, ebp
jmp .continue
@@:
mov eax, [esp+8]
add eax, 31
cmp dword [esp], flp_root_next
jnz @f
add eax, -31+19
@@:
add esp, 16 ; CF=0
pop esi
ret
 
;----------------------------------------------------------------
;
; fs_FloppyRead - LFN variant for reading floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_FloppyRead:
call read_flp_fat
cmp byte [esi], 0
jnz @f
or ebx, -1
mov eax, 10 ; access denied
ret
@@:
push edi
call fd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, 5 ; file not found
ret
.found:
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
xor ebx, ebx
.reteof:
mov eax, 6 ; EOF
pop edi
ret
@@:
mov ebx, [ebx]
.l1:
push ecx edx
push 0
mov eax, [edi+28]
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
mov byte [esp], 6 ; EOF
@@:
movzx edi, word [edi+26]
.new:
jecxz .done
test edi, edi
jz .eof
cmp edi, 0xFF8
jae .eof
sub ebx, 512
jae .skip
lea eax, [edi+31]
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .err
lea eax, [FDD_BUFF+ebx+512]
neg ebx
push ecx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
mov ebx, edx
call memmove
add edx, ecx
sub [esp], ecx
pop ecx
xor ebx, ebx
.skip:
movzx edi, word [edi*2+FLOPPY_FAT]
jmp .new
.done:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
ret
.eof:
mov ebx, edx
pop eax edx ecx
jmp .reteof
.err:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
mov al, 11
ret
 
;----------------------------------------------------------------
;
; fs_FloppyReadFolder - LFN variant for reading floppy folders
;
; esi points to filename
; ebx pointer to structure: 32-bit number = first wanted block, 0+
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_FloppyReadFolder:
call read_flp_fat
push edi
cmp byte [esi], 0
jz .root
call fd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
.found:
test byte [edi+11], 0x10 ; do not allow read files
jnz .found_dir
pop edi
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
.found_dir:
movzx eax, word [edi+26]
add eax, 31
push 0
jmp .doit
.root:
mov eax, 19
push 14
.doit:
push ecx ebp
sub esp, 262*2 ; reserve space for LFN
mov ebp, esp
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names
mov ebx, [ebx]
; init header
push eax ecx
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
pop ecx eax
mov byte [edx], 1 ; version
mov esi, edi ; esi points to BDFE
.main_loop:
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .error
mov edi, FDD_BUFF
push eax
.l1:
call fat_get_name
jc .l2
cmp byte [edi+11], 0xF
jnz .do_bdfe
add edi, 0x20
cmp edi, OS_BASE+0xD200
jb .do_bdfe
pop eax
inc eax
dec byte [esp+262*2+12]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+FLOPPY_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+12], 0
@@:
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .error
mov edi, FDD_BUFF
push eax
.do_bdfe:
inc dword [edx+8] ; new file found
dec ebx
jns .l2
dec ecx
js .l2
inc dword [edx+4] ; new file block copied
call fat_entry_to_bdfe
.l2:
add edi, 0x20
cmp edi, OS_BASE+0xD200
jb .l1
pop eax
inc eax
dec byte [esp+262*2+12]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+FLOPPY_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+12], 0
@@:
jmp .main_loop
.error:
add esp, 262*2+4
pop ebp ecx edi edi
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
.done:
add esp, 262*2+4
pop ebp
mov ebx, [edx+4]
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
pop ecx edi edi
ret
 
;----------------------------------------------------------------
;
; fs_FloppyRewrite - LFN variant for writing sys floppy
;
; esi points to filename
; ebx ignored (reserved)
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = number of written bytes
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
@@:
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
fsfrfe2:
popad
fsfrfe:
mov eax, 11
xor ebx, ebx
ret
 
fs_FloppyCreateFolder:
mov al, 1
jmp fs_FloppyRewrite.common
 
fs_FloppyRewrite:
xor eax, eax
.common:
cmp byte [esi], 0
jz @b
call read_flp_fat
cmp [FDC_Status], 0
jnz fsfrfe
pushad
xor edi, edi
push esi
test ebp, ebp
jz @f
mov esi, ebp
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
lea edi, [esi-1]
jmp @b
@@:
pop esi
test edi, edi
jnz .noroot
test ebp, ebp
jnz .hasebp
call read_flp_root
cmp [FDC_Status], 0
jnz fsfrfe2
push flp_rootmem_extend_dir
push flp_rootmem_end_write
push flp_rootmem_next_write
push flp_rootmem_begin_write
xor ebp, ebp
push ebp
push flp_rootmem_first
push flp_rootmem_next
jmp .common1
.hasebp:
mov eax, ERROR_ACCESS_DENIED
cmp byte [ebp], 0
jz .ret1
push ebp
xor ebp, ebp
call fd_find_lfn
pop esi
jc .notfound0
jmp .common0
.noroot:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edi+1], 0
jz .ret1
; check existence
mov byte [edi], 0
push edi
call fd_find_lfn
pop esi
mov byte [esi], '/'
jnc @f
.notfound0:
mov eax, ERROR_FILE_NOT_FOUND
.ret1:
mov [esp+28], eax
popad
xor ebx, ebx
ret
@@:
inc esi
.common0:
test byte [edi+11], 0x10 ; must be directory
mov eax, ERROR_ACCESS_DENIED
jz .ret1
movzx ebp, word [edi+26] ; ebp=cluster
mov eax, ERROR_FAT_TABLE
cmp ebp, 2
jb .ret1
cmp ebp, 2849
jae .ret1
push flp_notroot_extend_dir
push flp_notroot_end_write
push flp_notroot_next_write
push flp_notroot_begin_write
push ebp
push flp_notroot_first
push flp_notroot_next
.common1:
call fat_find_lfn
jc .notfound
; found
test byte [edi+11], 10h
jz .exists_file
; found directory; if we are creating directory, return OK,
; if we are creating file, say "access denied"
add esp, 28
popad
test al, al
mov eax, ERROR_ACCESS_DENIED
jz @f
mov al, 0
@@:
xor ebx, ebx
ret
.exists_file:
; found file; if we are creating directory, return "access denied",
; if we are creating file, delete existing file and continue
cmp byte [esp+28+28], 0
jz @f
add esp, 28
popad
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
@@:
; delete FAT chain
push edi
xor eax, eax
mov dword [edi+28], eax ; zero size
xchg ax, word [edi+26] ; start cluster
test eax, eax
jz .done1
@@:
cmp eax, 0xFF8
jae .done1
lea edi, [FLOPPY_FAT + eax*2] ; position in FAT
xor eax, eax
xchg ax, [edi]
jmp @b
.done1:
pop edi
call get_time_for_file
mov [edi+22], ax
call get_date_for_file
mov [edi+24], ax
mov [edi+18], ax
or byte [edi+11], 20h ; set 'archive' attribute
jmp .doit
.notfound:
; file is not found; generate short name
call fat_name_is_legal
jc @f
add esp, 28
popad
mov eax, ERROR_FILE_NOT_FOUND
xor ebx, ebx
ret
@@:
sub esp, 12
mov edi, esp
call fat_gen_short_name
.test_short_name_loop:
push esi edi ecx
mov esi, edi
lea eax, [esp+12+12+8]
mov [eax], ebp
call dword [eax-4]
jc .found
.test_short_name_entry:
cmp byte [edi+11], 0xF
jz .test_short_name_cont
mov ecx, 11
push esi edi
repz cmpsb
pop edi esi
jz .short_name_found
.test_short_name_cont:
lea eax, [esp+12+12+8]
call dword [eax-8]
jnc .test_short_name_entry
jmp .found
.short_name_found:
pop ecx edi esi
call fat_next_short_name
jnc .test_short_name_loop
.disk_full:
add esp, 12+28
popa
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.found:
pop ecx edi esi
; now find space in directory
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
mov al, '~'
push ecx edi
mov ecx, 8
repnz scasb
movi eax, 1 ; 1 entry
jnz .notilde
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
xor eax, eax
@@:
cmp byte [esi], 0
jz @f
inc esi
inc eax
jmp @b
@@:
sub esi, eax
add eax, 12+13
mov ecx, 13
push edx
cdq
div ecx
pop edx
.notilde:
push -1
push -1
; find <eax> successive entries in directory
xor ecx, ecx
push eax
lea eax, [esp+12+8+12+8]
mov [eax], ebp
call dword [eax-4]
pop eax
jnc .scan_dir
.fsfrfe3:
add esp, 8+8+12+28
popad
mov eax, 11
xor ebx, ebx
ret
.scan_dir:
cmp byte [edi], 0
jz .free
cmp byte [edi], 0xE5
jz .free
xor ecx, ecx
.scan_cont:
push eax
lea eax, [esp+12+8+12+8]
call dword [eax-8]
pop eax
jnc .scan_dir
cmp [FDC_Status], 0
jnz .fsfrfe3
push eax
lea eax, [esp+12+8+12+8]
call dword [eax+16] ; extend directory
pop eax
jnc .scan_dir
add esp, 8+8+12+28
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.free:
test ecx, ecx
jnz @f
mov [esp], edi
mov ecx, [esp+8+8+12+8]
mov [esp+4], ecx
xor ecx, ecx
@@:
inc ecx
cmp ecx, eax
jb .scan_cont
; found!
; calculate name checksum
push esi ecx
mov esi, [esp+8+8]
mov ecx, 11
xor eax, eax
@@:
ror al, 1
add al, [esi]
inc esi
loop @b
pop ecx esi
pop edi
pop dword [esp+8+12+8]
; edi points to first entry in free chunk
dec ecx
jz .nolfn
push esi
push eax
lea eax, [esp+8+8+12+8]
call dword [eax+4] ; begin write
mov al, 40h
.writelfn:
or al, cl
mov esi, [esp+4]
push ecx
dec ecx
imul ecx, 13
add esi, ecx
stosb
mov cl, 5
call fs_RamdiskRewrite.read_symbols
mov ax, 0xF
stosw
mov al, [esp+4]
stosb
mov cl, 6
call fs_RamdiskRewrite.read_symbols
xor eax, eax
stosw
mov cl, 2
call fs_RamdiskRewrite.read_symbols
pop ecx
lea eax, [esp+8+8+12+8]
call dword [eax+8] ; next write
xor eax, eax
loop .writelfn
pop eax
pop esi
; lea eax, [esp+8+12+8]
; call dword [eax+12] ; end write
.nolfn:
xchg esi, [esp]
mov ecx, 11
rep movsb
mov word [edi], 20h ; attributes
sub edi, 11
pop esi ecx
add esp, 12
mov byte [edi+13], 0 ; tenths of a second at file creation time
call get_time_for_file
mov [edi+14], ax ; creation time
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+16], ax ; creation date
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
and word [edi+20], 0 ; high word of cluster
and word [edi+26], 0 ; low word of cluster - to be filled
and dword [edi+28], 0 ; file size - to be filled
cmp byte [esp+28+28], 0
jz .doit
; create directory
mov byte [edi+11], 10h ; attributes: folder
mov ecx, 32*2
mov edx, edi
.doit:
lea eax, [esp+8]
call dword [eax+12] ; flush directory
push ecx
push edi
push 0
mov esi, edx
test ecx, ecx
jz .done
mov ecx, 2849
mov edi, FLOPPY_FAT
push 0 ; first cluster
.write_loop:
; allocate new cluster
xor eax, eax
repnz scasw
mov al, ERROR_DISK_FULL
jnz .ret
dec edi
dec edi
 
mov eax, edi
sub eax, FLOPPY_FAT
 
shr eax, 1 ; eax = cluster
mov word [edi], 0xFFF ; mark as last cluster
xchg edi, [esp+4]
cmp dword [esp], 0
jz .first
stosw
jmp @f
.first:
mov [esp], eax
@@:
mov edi, [esp+4]
inc ecx
; write data
push ecx edi
mov ecx, 512
cmp dword [esp+20], ecx
jae @f
mov ecx, [esp+20]
@@:
mov edi, FDD_BUFF
cmp byte [esp+24+28+28], 0
jnz .writedir
push ecx
rep movsb
pop ecx
.writedircont:
push ecx
sub ecx, 512
neg ecx
push eax
xor eax, eax
rep stosb
pop eax
add eax, 31
pusha
call save_chs_sector
popa
pop ecx
cmp [FDC_Status], 0
jnz .diskerr
sub [esp+20], ecx
pop edi ecx
jnz .write_loop
.done:
xor eax, eax
.ret:
pop ebx edi edi ecx
mov [esp+28+28], eax
lea eax, [esp+8]
call dword [eax+4]
mov [edi+26], bx
mov ebx, esi
sub ebx, edx
mov [edi+28], ebx
call dword [eax+12]
mov [esp+28+16], ebx
test ebp, ebp
jnz @f
call save_flp_root
@@:
add esp, 28
cmp [FDC_Status], 0
jnz .err3
call save_flp_fat
cmp [FDC_Status], 0
jnz .err3
popa
ret
.err3:
popa
mov al, 11
xor ebx, ebx
ret
.diskerr:
sub esi, ecx
mov eax, 11
pop edi ecx
jmp .ret
.writedir:
push ecx
mov ecx, 32/4
push ecx esi
rep movsd
pop esi ecx
mov dword [edi-32], '. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov word [edi-32+26], ax
push esi
rep movsd
pop esi
mov dword [edi-32], '.. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov ecx, [esp+28+8]
mov word [edi-32+26], cx
pop ecx
jmp .writedircont
 
;----------------------------------------------------------------
;
; fs_FloppyWrite - LFN variant for writing to floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = bytes written (maybe 0)
; eax = 0 ok write or other = errormsg
;
;--------------------------------------------------------------
 
@@:
push ERROR_ACCESS_DENIED
fs_FloppyWrite.ret0:
pop eax
xor ebx, ebx
ret
 
fs_FloppyWrite.ret11:
push 11
jmp fs_FloppyWrite.ret0
 
fs_FloppyWrite:
cmp byte [esi], 0
jz @b
call read_flp_fat
cmp [FDC_Status], 0
jnz .ret11
pushad
call fd_find_lfn
jnc .found
popad
push ERROR_FILE_NOT_FOUND
jmp .ret0
.found:
; FAT does not support files larger than 4GB
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
.eof:
popad
push ERROR_END_OF_FILE
jmp .ret0
@@:
mov ebx, [ebx]
.l1:
; now edi points to direntry, ebx=start byte to write,
; ecx=number of bytes to write, edx=data pointer
 
; extend file if needed
add ecx, ebx
jc .eof ; FAT does not support files larger than 4GB
push eax ; save directory cluster
push 0 ; return value=0
 
call get_time_for_file
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
 
push dword [edi+28] ; save current file size
cmp ecx, [edi+28]
jbe .length_ok
cmp ecx, ebx
jz .length_ok
call floppy_extend_file
jnc .length_ok
mov [esp+4], eax
; floppy_extend_file can return two error codes: FAT table error or disk full.
; First case is fatal error, in second case we may write some data
cmp al, ERROR_DISK_FULL
jz .disk_full
pop eax
pop eax
mov [esp+4+28], eax
pop eax
popad
xor ebx, ebx
ret
.disk_full:
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
.ret:
pop eax
pop eax
mov [esp+4+28], eax ; eax=return value
pop eax
sub edx, [esp+20]
mov [esp+16], edx ; ebx=number of written bytes
popad
ret
.length_ok:
; save FAT & directory
; note that directory must be saved first because save_flp_fat uses buffer at 0xD000
mov esi, [edi+28]
movzx edi, word [edi+26] ; starting cluster
mov eax, [esp+8]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err
call save_flp_fat
cmp [FDC_Status], 0
jz @f
.device_err:
mov byte [esp+4], 11
jmp .ret
@@:
 
; now ebx=start pos, ecx=end pos, both lie inside file
sub ecx, ebx
jz .ret
 
.write_loop:
; skip unmodified sectors
cmp dword [esp], 0x200
jb .modify
sub ebx, 0x200
jae .skip
add ebx, 0x200
.modify:
lea eax, [edi+31] ; current sector
; get length of data in current sector
push ecx
sub ebx, 0x200
jb .hasdata
neg ebx
xor ecx, ecx
jmp @f
.hasdata:
neg ebx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
; load sector if needed
cmp dword [esp+4], 0 ; we don't need to read uninitialized data
jz .noread
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten
jz .noread
cmp ecx, esi ; (same for the last sector)
jz .noread
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jz @f
.device_err2:
pop ecx
jmp .device_err
@@:
.noread:
; zero uninitialized data if file was extended (because floppy_extend_file does not this)
push eax ecx edi
xor eax, eax
mov ecx, 0x200
sub ecx, [esp+4+12]
jbe @f
mov edi, FDD_BUFF
add edi, [esp+4+12]
rep stosb
@@:
; zero uninitialized data in the last sector
mov ecx, 0x200
sub ecx, esi
jbe @f
mov edi, FDD_BUFF
add edi, esi
rep stosb
@@:
pop edi ecx eax
; copy new data
push eax
mov eax, edx
neg ebx
jecxz @f
add ebx, FDD_BUFF+0x200
call memmove
xor ebx, ebx
@@:
pop eax
; save sector
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err2
add edx, ecx
sub [esp], ecx
pop ecx
jz .done
.skip:
.next_cluster:
movzx edi, word [edi*2+FLOPPY_FAT]
sub esi, 0x200
jae @f
xor esi, esi
@@:
sub dword [esp], 0x200
jae .write_loop
and dword [esp], 0
jmp .write_loop
.done:
jmp .ret
 
floppy_extend_file.zero_size:
xor eax, eax
jmp floppy_extend_file.start_extend
 
; extends file on floppy to given size (new data area is undefined)
; in: edi->direntry, ecx=new size
; out: CF=0 => OK, eax=0
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
floppy_extend_file:
push ecx
; find the last cluster of file
movzx eax, word [edi+26] ; first cluster
mov ecx, [edi+28]
jecxz .zero_size
@@:
sub ecx, 0x200
jbe @f
mov eax, [eax*2+FLOPPY_FAT]
and eax, 0xFFF
jz .fat_err
cmp eax, 0xFF8
jb @b
.fat_err:
pop ecx
movi eax, ERROR_FAT_TABLE
stc
ret
@@:
push eax
mov eax, [eax*2+FLOPPY_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
pop eax
jb .fat_err
; set length to full number of sectors
sub [edi+28], ecx
.start_extend:
pop ecx
; now do extend
push edx esi
mov esi, FLOPPY_FAT+2*2 ; start scan from cluster 2
mov edx, 2847 ; number of clusters to scan
.extend_loop:
cmp [edi+28], ecx
jae .extend_done
; add new sector
push ecx
push edi
.scan:
mov ecx, edx
mov edi, esi
jecxz .disk_full
push eax
xor eax, eax
repnz scasw
pop eax
jnz .disk_full
mov word [edi-2], 0xFFF
mov esi, edi
mov edx, ecx
sub edi, FLOPPY_FAT
shr edi, 1
dec edi ; now edi=new cluster
test eax, eax
jz .first_cluster
mov [FLOPPY_FAT+eax*2], di
jmp @f
.first_cluster:
pop eax ; eax->direntry
push eax
mov [eax+26], di
@@:
mov eax, edi ; eax=new cluster
pop edi ; edi->direntry
pop ecx ; ecx=required size
add dword [edi+28], 0x200
jmp .extend_loop
.extend_done:
mov [edi+28], ecx
pop esi edx
xor eax, eax ; CF=0
ret
.disk_full:
pop edi ecx
pop esi edx
stc
movi eax, ERROR_DISK_FULL
ret
 
;----------------------------------------------------------------
;
; fs_FloppySetFileEnd - set end of file on floppy
;
; esi points to filename
; ebx points to 64-bit number = new file size
; ecx ignored (reserved)
; edx ignored (reserved)
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_FloppySetFileEnd:
call read_flp_fat
cmp [FDC_Status], 0
jnz ret11
cmp byte [esi], 0
jnz @f
.access_denied:
push ERROR_ACCESS_DENIED
jmp .ret
@@:
push edi
call fd_find_lfn
jnc @f
pop edi
push ERROR_FILE_NOT_FOUND
.ret:
pop eax
jmp .doret
@@:
; must not be directory
test byte [edi+11], 10h
jz @f
pop edi
jmp .access_denied
@@:
; file size must not exceed 4 Gb
cmp dword [ebx+4], 0
jz @f
pop edi
push ERROR_END_OF_FILE
jmp .ret
@@:
push eax
; set file modification date/time to current
call fat_update_datetime
mov eax, [ebx]
cmp eax, [edi+28]
jb .truncate
ja .expand
pop eax
pushad
call save_chs_sector
popad
pop edi
xor eax, eax
cmp [FDC_Status], 0
jz @f
mov al, 11
@@:
.doret:
ret
.expand:
push ecx
push dword [edi+28] ; save old size
mov ecx, eax
call floppy_extend_file
push eax ; return code
jnc .expand_ok
cmp al, ERROR_DISK_FULL
jz .disk_full
pop eax ecx ecx edi edi
jmp .doret
.device_err:
pop eax
.device_err2:
pop ecx ecx eax edi
push 11
jmp .ret
.disk_full:
.expand_ok:
; save directory & FAT
mov eax, [edi+28]
xchg eax, [esp+12]
movzx edi, word [edi+26]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err
call save_flp_fat
cmp [FDC_Status], 0
jnz .device_err
; now zero new data
; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code
.zero_loop:
sub dword [esp+4], 0x200
jae .next_cluster
cmp dword [esp+4], -0x200
jz .noread
lea eax, [edi+31]
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .err_next
.noread:
mov ecx, [esp+4]
neg ecx
push edi
mov edi, FDD_BUFF+0x200
add edi, [esp+8]
xor eax, eax
mov [esp+8], eax
rep stosb
pop edi
lea eax, [edi+31]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jz .next_cluster
.err_next:
mov byte [esp], 11
.next_cluster:
sub dword [esp+12], 0x200
jbe .expand_done
movzx edi, word [FLOPPY_FAT+edi*2]
jmp .zero_loop
.expand_done:
pop eax ecx ecx edi edi
jmp .doret
.truncate:
mov [edi+28], eax
push ecx
movzx ecx, word [edi+26]
test eax, eax
jz .zero_size
; find new last sector
@@:
sub eax, 0x200
jbe @f
movzx ecx, word [FLOPPY_FAT+ecx*2]
jmp @b
@@:
; we will zero data at the end of last sector - remember it
push ecx
; terminate FAT chain
lea ecx, [FLOPPY_FAT+ecx+ecx]
push dword [ecx]
mov word [ecx], 0xFFF
pop ecx
and ecx, 0xFFF
jmp .delete
.zero_size:
and word [edi+26], 0
push 0
.delete:
; delete FAT chain starting with ecx
; mark all clusters as free
cmp ecx, 0xFF8
jae .deleted
lea ecx, [FLOPPY_FAT+ecx+ecx]
push dword [ecx]
and word [ecx], 0
pop ecx
and ecx, 0xFFF
jmp .delete
.deleted:
mov edi, [edi+28]
; save directory & FAT
mov eax, [esp+8]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err2
call save_flp_fat
cmp [FDC_Status], 0
jnz .device_err2
; zero last sector, ignore errors
pop eax
add eax, 31
and edi, 0x1FF
jz .truncate_done
 
pusha
call read_chs_sector
popa
add edi, FDD_BUFF
mov ecx, FDD_BUFF+0x200
sub ecx, edi
push eax
xor eax, eax
rep stosb
pop eax
pusha
call save_chs_sector
popa
.truncate_done:
pop ecx eax edi
xor eax, eax
jmp .doret
 
fs_FloppyGetFileInfo:
call read_flp_fat
cmp [FDC_Status], 0
jnz ret11
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call fd_find_lfn
jmp fs_GetFileInfo_finish
 
ret11:
mov eax, 11
ret
 
fs_FloppySetFileInfo:
call read_flp_fat
cmp [FDC_Status], 0
jnz ret11
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call fd_find_lfn
jnc @f
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
@@:
push eax
call bdfe_to_fat_entry
pop eax
pusha
call save_chs_sector
popa
pop edi
xor eax, eax
cmp [FDC_Status], al
jz @f
mov al, 11
@@:
ret
 
;----------------------------------------------------------------
;
; fs_FloppyDelete - delete file or empty folder from floppy
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_FloppyDelete:
call read_flp_fat
cmp [FDC_Status], 0
jz @f
push 11
jmp .pop_ret
@@:
cmp byte [esi], 0
jnz @f
; cannot delete root!
.access_denied:
push ERROR_ACCESS_DENIED
.pop_ret:
pop eax
ret
@@:
and [fd_prev_sector], 0
and [fd_prev_prev_sector], 0
push edi
call fd_find_lfn
jnc .found
pop edi
push ERROR_FILE_NOT_FOUND
jmp .pop_ret
.found:
cmp dword [edi], '. '
jz .access_denied2
cmp dword [edi], '.. '
jz .access_denied2
test byte [edi+11], 10h
jz .dodel
; we can delete only empty folders!
push eax
movzx eax, word [edi+26]
push ebx
pusha
add eax, 31
call read_chs_sector
popa
mov ebx, FDD_BUFF + 2*0x20
.checkempty:
cmp byte [ebx], 0
jz .empty
cmp byte [ebx], 0xE5
jnz .notempty
add ebx, 0x20
cmp ebx, FDD_BUFF + 0x200
jb .checkempty
movzx eax, word [FLOPPY_FAT + eax*2]
pusha
add eax, 31
call read_chs_sector
popa
mov ebx, FDD_BUFF
jmp .checkempty
.notempty:
pop ebx
pop eax
.access_denied2:
pop edi
jmp .access_denied
.empty:
pop ebx
pop eax
pusha
call read_chs_sector
popa
.dodel:
push eax
movzx eax, word [edi+26]
xchg eax, [esp]
; delete folder entry
mov byte [edi], 0xE5
; delete LFN (if present)
.lfndel:
cmp edi, FDD_BUFF
ja @f
cmp [fd_prev_sector], 0
jz .lfndone
push [fd_prev_sector]
push [fd_prev_prev_sector]
pop [fd_prev_sector]
and [fd_prev_prev_sector], 0
pusha
call save_chs_sector
popa
pop eax
pusha
call read_chs_sector
popa
mov edi, FDD_BUFF+0x200
@@:
sub edi, 0x20
cmp byte [edi], 0xE5
jz .lfndone
cmp byte [edi+11], 0xF
jnz .lfndone
mov byte [edi], 0xE5
jmp .lfndel
.lfndone:
pusha
call save_chs_sector
popa
; delete FAT chain
pop eax
@@:
cmp eax, 2
jb .done
cmp eax, 0xFF8
jae .done
lea eax, [FLOPPY_FAT + eax*2]
push dword [eax]
and word [eax], 0
pop eax
and eax, 0xFFF
jmp @b
.done:
call save_flp_fat
pop edi
xor eax, eax
ret
 
; \end{diamond}
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/fs/fat32.inc
0,0 → 1,2671
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FAT32.INC ;;
;; ;;
;; FAT16/32 functions for KolibriOS ;;
;; ;;
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;;
;; ;;
;; See file COPYING for details ;;
;; 04.02.2007 LFN create folder - diamond ;;
;; 08.10.2006 LFN delete file/folder - diamond ;;
;; 20.08.2006 LFN set file size (truncate/extend) - diamond ;;
;; 17.08.2006 LFN write/append to file - diamond ;;
;; 23.06.2006 LFN start application - diamond ;;
;; 15.06.2006 LFN get/set file/folder info - diamond ;;
;; 27.05.2006 LFN create/rewrite file - diamond ;;
;; 04.05.2006 LFN read folder - diamond ;;
;; 29.04.2006 Elimination of hangup after the ;;
;; expiration hd_wait_timeout - Mario79 ;;
;; 23.04.2006 LFN read file - diamond ;;
;; 28.01.2006 find all Fat16/32 partition in all input point ;;
;; to MBR, see file part_set.inc - Mario79 ;;
;; 15.01.2005 get file size/attr/date, file_append - ATV ;;
;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;;
;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;;
;; 23.11.2004 don't allow overwrite dir with file - ATV ;;
;; 18.11.2004 get_disk_info and more error codes - ATV ;;
;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;;
;; 10.11.2004 removedir clear whole directory structure - ATV ;;
;; 08.11.2004 rename - ATV ;;
;; 30.10.2004 file_read return also dirsize in bytes - ATV ;;
;; 20.10.2004 Makedir/Removedir - ATV ;;
;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;;
;; 06.9.2004 Fix free space by Mario79 added - MH ;;
;; 24.5.2004 Write back buffer for File_write -VT ;;
;; 20.5.2004 File_read function to work with syscall 58 - VT ;;
;; 30.3.2004 Error parameters at function return - VT ;;
;; 01.5.2002 Bugfix in device write - VT ;;
;; 20.5.2002 Hd status check - VT ;;
;; 29.6.2002 Improved fat32 verification - VT ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00
 
PUSHAD_EAX equ [esp+28]
PUSHAD_ECX equ [esp+24]
PUSHAD_EDX equ [esp+20]
PUSHAD_EBX equ [esp+16]
PUSHAD_EBP equ [esp+8]
PUSHAD_ESI equ [esp+4]
PUSHAD_EDI equ [esp+0]
 
; Internal data for every FAT partition.
struct FAT PARTITION
fs_type db ?
fat16_root db 0 ; flag for fat16 rootdir
fat_change db 0 ; 1=fat has changed
db ? ; alignment
Lock MUTEX ? ; currently operations with one partition
; can not be executed in parallel since the
; legacy code is not ready; this mutex guards
; all operations
SECTORS_PER_FAT dd 0x1f3a
NUMBER_OF_FATS dd 0x2
SECTORS_PER_CLUSTER dd 0x8
BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes
ROOT_CLUSTER dd 2 ; first rootdir cluster
FAT_START dd 0 ; start of fat table
ROOT_START dd 0 ; start of rootdir (only fat16)
ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16)
DATA_START dd 0 ; start of data area (=first cluster 2)
LAST_CLUSTER dd 0 ; last availabe cluster
ADR_FSINFO dd 0 ; used only by fat32
 
fatRESERVED dd 0x0FFFFFF6
fatBAD dd 0x0FFFFFF7
fatEND dd 0x0FFFFFF8
fatMASK dd 0x0FFFFFFF
 
fatStartScan dd 2
 
cluster_tmp dd 0 ; used by analyze_directory
; and analyze_directory_to_write
 
longname_sec1 dd 0 ; used by analyze_directory to save 2 previous
longname_sec2 dd 0 ; directory sectors for delete long filename
 
fat_in_cache dd -1
 
fat_cache rb 512
buffer rb 512
fsinfo_buffer rb 512
ends
 
uglobal
align 4
partition_count dd 0 ; partitions found by set_FAT32_variables
 
hd_error dd 0 ; set by wait_for_sector_buffer
hd_setup dd 0
hd_wait_timeout dd 0
 
cache_search_start dd 0 ; used by find_empty_slot
endg
 
uglobal
align 4
Sector512: ; label for dev_hdcd.inc
buffer:
times 512 db 0
endg
 
iglobal
align 4
fat_user_functions:
dd free
dd (fat_user_functions_end - fat_user_functions - 4) / 4
dd fat_Read
dd fat_ReadFolder
dd fat_Rewrite
dd fat_Write
dd fat_SetFileEnd
dd fat_GetFileInfo
dd fat_SetFileInfo
dd 0
dd fat_Delete
dd fat_CreateFolder
fat_user_functions_end:
endg
 
; these labels are located before the main function to make
; most of jumps to these be short
fat_create_partition.free_return0:
mov eax, ebp
call free
pop ebp
fat_create_partition.return0:
xor eax, eax
ret
fat_create_partition:
; bootsector must have been successfully read
cmp dword [esp+4], 0
jnz .return0
; bootsector signature must be correct
cmp word [ebx+0x1fe], 0xaa55
jnz .return0
; sectors per cluster must be nonzero
cmp byte [ebx+0xd], 0
jz .return0
; bytes per sector must be 0x200
cmp word [ebx+0xb], 0x200
jnz .return0
; number of fats must be nonzero
cmp byte [ebx+0x10], 0
jz .return0
; The only reason to be invalid partition now is FAT12. Since the test for
; FAT size requires knowledge of some calculated values, which are also used
; in the normal operation, let's hope for the best and allocate data now; if
; it will prove wrong, just deallocate it.
movi eax, sizeof.FAT
call malloc
test eax, eax
jz .return0
mov ecx, dword [ebp+PARTITION.FirstSector]
mov dword [eax+FAT.FirstSector], ecx
mov ecx, dword [ebp+PARTITION.FirstSector+4]
mov dword [eax+FAT.FirstSector+4], ecx
mov ecx, dword [ebp+PARTITION.Length]
mov dword [eax+FAT.Length], ecx
mov ecx, dword [ebp+PARTITION.Length+4]
mov dword [eax+FAT.Length+4], ecx
mov ecx, [ebp+PARTITION.Disk]
mov [eax+FAT.Disk], ecx
mov [eax+FAT.FSUserFunctions], fat_user_functions
or [eax+FAT.fat_in_cache], -1
mov [eax+FAT.fat_change], 0
push ebp
mov ebp, eax
 
lea ecx, [ebp+FAT.Lock]
call mutex_init
 
movzx eax, word [ebx+0xe] ; sectors reserved
mov [ebp+FAT.FAT_START], eax
 
movzx eax, byte [ebx+0xd] ; sectors per cluster
mov [ebp+FAT.SECTORS_PER_CLUSTER], eax
 
movzx ecx, word [ebx+0xb] ; bytes per sector
mov [ebp+FAT.BYTES_PER_SECTOR], ecx
 
movzx eax, word [ebx+0x11] ; count of rootdir entries (=0 fat32)
shl eax, 5 ; mul 32
dec ecx
add eax, ecx ; round up if not equal count
inc ecx ; bytes per sector
xor edx, edx
div ecx
mov [ebp+FAT.ROOT_SECTORS], eax ; count of rootdir sectors
 
movzx eax, word [ebx+0x16] ; sectors per fat <65536
test eax, eax
jnz @f
mov eax, [ebx+0x24] ; sectors per fat
@@:
mov [ebp+FAT.SECTORS_PER_FAT], eax
 
movzx eax, byte [ebx+0x10] ; number of fats
mov [ebp+FAT.NUMBER_OF_FATS], eax
imul eax, [ebp+FAT.SECTORS_PER_FAT]
add eax, [ebp+FAT.FAT_START]
mov [ebp+FAT.ROOT_START], eax ; rootdir = fat_start + fat_size * fat_count
add eax, [ebp+FAT.ROOT_SECTORS] ; rootdir sectors should be 0 on fat32
mov [ebp+FAT.DATA_START], eax ; data area = rootdir + rootdir_size
 
movzx eax, word [ebx+0x13] ; total sector count <65536
test eax, eax
jnz @f
mov eax, [ebx+0x20] ; total sector count
@@:
mov dword [ebp+FAT.Length], eax
and dword [ebp+FAT.Length+4], 0
sub eax, [ebp+FAT.DATA_START] ; eax = count of data sectors
xor edx, edx
div [ebp+FAT.SECTORS_PER_CLUSTER]
inc eax
mov [ebp+FAT.LAST_CLUSTER], eax
dec eax ; cluster count
mov [ebp+FAT.fatStartScan], 2
 
; limits by Microsoft Hardware White Paper v1.03
cmp eax, 4085 ; 0xff5
jb .free_return0 ; fat12 not supported
cmp eax, 65525 ; 0xfff5
jb .fat16
.fat32:
mov eax, [ebx+0x2c] ; rootdir cluster
mov [ebp+FAT.ROOT_CLUSTER], eax
movzx eax, word [ebx+0x30]
mov [ebp+FAT.ADR_FSINFO], eax
push ebx
add ebx, 512
call fs_read32_sys
test eax, eax
jnz @f
mov eax, [ebx+0x1ec]
cmp eax, -1
jz @f
mov [ebp+FAT.fatStartScan], eax
@@:
pop ebx
mov [ebp+FAT.fatRESERVED], 0x0FFFFFF6
mov [ebp+FAT.fatBAD], 0x0FFFFFF7
mov [ebp+FAT.fatEND], 0x0FFFFFF8
mov [ebp+FAT.fatMASK], 0x0FFFFFFF
mov al, 32
mov [ebp+FAT.fs_type], al
mov eax, ebp
pop ebp
ret
.fat16:
and [ebp+FAT.ROOT_CLUSTER], 0
mov [ebp+FAT.fatRESERVED], 0x0000FFF6
mov [ebp+FAT.fatBAD], 0x0000FFF7
mov [ebp+FAT.fatEND], 0x0000FFF8
mov [ebp+FAT.fatMASK], 0x0000FFFF
mov al, 16
mov [ebp+FAT.fs_type], al
mov eax, ebp
pop ebp
ret
 
set_FAT:
;--------------------------------
; input : EAX = cluster
; EDX = value to save
; EBP = pointer to FAT structure
; output : EDX = old value
;--------------------------------
; out: CF set <=> error
push eax ebx esi
 
cmp eax, 2
jb sfc_error
cmp eax, [ebp+FAT.LAST_CLUSTER]
ja sfc_error
cmp [ebp+FAT.fs_type], 16
je sfc_1
add eax, eax
sfc_1:
add eax, eax
mov esi, 511
and esi, eax ; esi = position in fat sector
shr eax, 9 ; eax = fat sector
add eax, [ebp+FAT.FAT_START]
lea ebx, [ebp+FAT.fat_cache]
 
cmp eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
je sfc_in_cache ; yes
 
cmp [ebp+FAT.fat_change], 0; is fat changed?
je sfc_no_change ; no
call write_fat_sector; yes. write it into disk
jc sfc_error
 
sfc_no_change:
mov [ebp+FAT.fat_in_cache], eax; save fat sector
call fs_read32_sys
test eax, eax
jne sfc_error
 
 
sfc_in_cache:
cmp [ebp+FAT.fs_type], 16
jne sfc_test32
 
sfc_set16:
xchg [ebx+esi], dx ; save new value and get old value
jmp sfc_write
 
sfc_test32:
mov eax, [ebp+FAT.fatMASK]
 
sfc_set32:
and edx, eax
xor eax, -1 ; mask for high bits
and eax, [ebx+esi] ; get high 4 bits
or eax, edx
mov edx, [ebx+esi] ; get old value
mov [ebx+esi], eax ; save new value
 
sfc_write:
mov [ebp+FAT.fat_change], 1; fat has changed
 
sfc_nonzero:
and edx, [ebp+FAT.fatMASK]
 
sfc_return:
pop esi ebx eax
ret
sfc_error:
stc
jmp sfc_return
 
 
get_FAT:
;--------------------------------
; input : EAX = cluster
; EBP = pointer to FAT structure
; output : EAX = next cluster
;--------------------------------
; out: CF set <=> error
push ebx esi
 
cmp [ebp+FAT.fs_type], 16
je gfc_1
add eax, eax
gfc_1:
add eax, eax
mov esi, 511
and esi, eax ; esi = position in fat sector
shr eax, 9 ; eax = fat sector
add eax, [ebp+FAT.FAT_START]
lea ebx, [ebp+FAT.fat_cache]
 
cmp eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
je gfc_in_cache
 
cmp [ebp+FAT.fat_change], 0; is fat changed?
je gfc_no_change ; no
call write_fat_sector; yes. write it into disk
jc hd_error_01
 
gfc_no_change:
mov [ebp+FAT.fat_in_cache], eax
call fs_read32_sys
test eax, eax
jne hd_error_01
 
gfc_in_cache:
mov eax, [ebx+esi]
and eax, [ebp+FAT.fatMASK]
gfc_return:
pop esi ebx
ret
hd_error_01:
stc
jmp gfc_return
 
 
get_free_FAT:
;-----------------------------------------------------------
; output : if CARRY=0 EAX = # first cluster found free
; if CARRY=1 disk full
; Note : for more speed need to use fat_cache directly
;-----------------------------------------------------------
push ecx
mov ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
sub ecx, 2
mov eax, [ebp+FAT.fatStartScan]
cmp eax, 2
jb gff_reset
 
gff_test:
cmp eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
jbe gff_in_range
gff_reset:
mov eax, 2
 
gff_in_range:
push eax
call get_FAT ; get cluster state
jc gff_not_found_1
 
test eax, eax ; is it free?
pop eax
je gff_found ; yes
inc eax ; next cluster
dec ecx ; is all checked?
jns gff_test ; no
 
gff_not_found:
pop ecx ; yes. disk is full
stc
ret
 
gff_not_found_1:
pop eax
jmp gff_not_found
 
gff_found:
lea ecx, [eax+1]
mov [ebp+FAT.fatStartScan], ecx
pop ecx
clc
ret
 
 
write_fat_sector:
;-----------------------------------------------------------
; write changed fat to disk
;-----------------------------------------------------------
push eax ebx ecx
 
mov [ebp+FAT.fat_change], 0
mov eax, [ebp+FAT.fat_in_cache]
cmp eax, -1
jz write_fat_not_used
lea ebx, [ebp+FAT.fat_cache]
mov ecx, [ebp+FAT.NUMBER_OF_FATS]
 
write_next_fat:
push eax
call fs_write32_sys
test eax, eax
pop eax
jnz write_fat_not_used
 
add eax, [ebp+FAT.SECTORS_PER_FAT]
dec ecx
jnz write_next_fat
 
write_fat_not_used:
pop ecx ebx eax
ret
 
 
 
 
 
bcd2bin:
;----------------------------------
; input : AL=BCD number (eg. 0x11)
; output : AH=0
; AL=decimal number (eg. 11)
;----------------------------------
xor ah, ah
shl ax, 4
shr al, 4
aad
ret
 
 
get_date_for_file:
;-----------------------------------------------------
; Get date from CMOS and pack day,month,year in AX
; DATE bits 0..4 : day of month 0..31
; 5..8 : month of year 1..12
; 9..15 : count of years from 1980
;-----------------------------------------------------
mov al, 0x7 ;day
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 5
 
mov al, 0x8 ;month
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 4
 
mov al, 0x9 ;year
out 0x70, al
in al, 0x71
call bcd2bin
add ax, 20 ;because CMOS return only the two last
;digit (eg. 2000 -> 00 , 2001 -> 01) and we
rol eax, 9 ;need the difference with 1980 (eg. 2001-1980)
ret
 
 
get_time_for_file:
;-----------------------------------------------------
; Get time from CMOS and pack hour,minute,second in AX
; TIME bits 0..4 : second (the low bit is lost)
; 5..10 : minute 0..59
; 11..15 : hour 0..23
;-----------------------------------------------------
mov al, 0x0 ;second
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 6
 
mov al, 0x2 ;minute
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 6
 
mov al, 0x4 ;hour
out 0x70, al
in al, 0x71
call bcd2bin
rol eax, 11
ret
 
 
set_current_time_for_entry:
;-----------------------------------------------------
; Set current time/date for file entry
; input : ebx = file entry pointer
;-----------------------------------------------------
push eax
call get_time_for_file; update files date/time
mov [ebx+22], ax
call get_date_for_file
mov [ebx+24], ax
pop eax
ret
 
 
 
add_disk_free_space:
;-----------------------------------------------------
; input : ecx = cluster count
; Note : negative = remove clusters from free space
; positive = add clusters to free space
;-----------------------------------------------------
test ecx, ecx ; no change
je add_dfs_no
cmp [ebp+FAT.fs_type], 32 ; free disk space only used by fat32
jne add_dfs_no
 
push eax ebx
mov eax, [ebp+FAT.ADR_FSINFO]
lea ebx, [ebp+FAT.fsinfo_buffer]
call fs_read32_sys
test eax, eax
jnz add_not_fs
 
cmp dword [ebx+0x1fc], 0xaa550000; check sector id
jne add_not_fs
 
add [ebx+0x1e8], ecx
push [ebp+FAT.fatStartScan]
pop dword [ebx+0x1ec]
mov eax, [ebp+FAT.ADR_FSINFO]
call fs_write32_sys
; jc add_not_fs
 
add_not_fs:
pop ebx eax
 
add_dfs_no:
ret
 
 
 
clear_cluster_chain:
;-----------------------------------------------------
; input : eax = first cluster
;-----------------------------------------------------
push eax ecx edx
xor ecx, ecx ; cluster count
 
clean_new_chain:
cmp eax, [ebp+FAT.LAST_CLUSTER]; end of file
ja delete_OK
cmp eax, 2 ; unfinished fat chain or zero length file
jb delete_OK
cmp eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
jz delete_OK
 
xor edx, edx
call set_FAT ; clear fat entry
jc access_denied_01
 
inc ecx ; update cluster count
mov eax, edx ; old cluster
jmp clean_new_chain
 
delete_OK:
call add_disk_free_space; add clusters to free disk space
clc
access_denied_01:
pop edx ecx eax
ret
 
 
if 0
get_hd_info:
;-----------------------------------------------------------
; output : eax = 0 - ok
; 3 - unknown FS
; 10 - access denied
; edx = cluster size in bytes
; ebx = total clusters on disk
; ecx = free clusters on disk
;-----------------------------------------------------------
cmp [ebp+FAT.fs_type], 16
jz info_fat_ok
cmp [ebp+FAT.fs_type], 32
jz info_fat_ok
xor edx, edx
xor ebx, ebx
xor ecx, ecx
mov eax, ERROR_UNKNOWN_FS
ret
 
info_fat_ok:
; call reserve_hd1
 
xor ecx, ecx ; count of free clusters
mov eax, 2
mov ebx, [ebp+FAT.LAST_CLUSTER]
 
info_cluster:
push eax
call get_FAT ; get cluster info
jc info_access_denied
 
test eax, eax ; is it free?
jnz info_used ; no
inc ecx
 
info_used:
pop eax
inc eax
cmp eax, ebx ; is above last cluster?
jbe info_cluster ; no. test next cluster
 
dec ebx ; cluster count
imul edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
xor eax, eax
ret
 
info_access_denied:
add esp, 4
xor edx, edx
xor ebx, ebx
xor ecx, ecx
mov eax, ERROR_ACCESS_DENIED
ret
end if
 
update_disk:
;-----------------------------------------------------------
; write changed fat and cache to disk
;-----------------------------------------------------------
cmp [ebp+FAT.fat_change], 0 ; is fat changed?
je upd_no_change
 
call write_fat_sector
jc update_disk_acces_denied
 
upd_no_change:
 
push esi
mov esi, [ebp+PARTITION.Disk]
call disk_sync
pop esi
update_disk_acces_denied:
ret
 
fat_lock:
lea ecx, [ebp+FAT.Lock]
jmp mutex_lock
fat_unlock:
lea ecx, [ebp+FAT.Lock]
jmp mutex_unlock
 
; \begin{diamond}
hd_find_lfn:
; in: ebp -> FAT structure
; in: esi+[esp+4] -> name
; out: CF=1 - file not found, eax=error code
; else CF=0 and edi->direntry, eax=sector
; destroys eax
push esi edi
push 0
push 0
push fat16_root_first
push fat16_root_next
mov eax, [ebp+FAT.ROOT_CLUSTER]
cmp [ebp+FAT.fs_type], 32
jz .fat32
.loop:
call fat_find_lfn
jc .notfound
cmp byte [esi], 0
jz .found
.continue:
test byte [edi+11], 10h
jz .notfound
and dword [esp+12], 0
mov eax, [edi+20-2]
mov ax, [edi+26] ; cluster
.fat32:
mov [esp+8], eax
mov dword [esp+4], fat_notroot_first
mov dword [esp], fat_notroot_next
jmp .loop
.notfound:
add esp, 16
pop edi esi
stc
ret 4
.found:
lea eax, [esp+4+24]
cmp dword [eax], 0
jz @f
mov esi, [eax]
and dword [eax], 0
jmp .continue
@@:
lea eax, [esp+8]
cmp dword [eax], 0
jz .root
call fat_get_sector
jmp .cmn
.root:
mov eax, [eax+4]
add eax, [ebp+FAT.ROOT_START]
.cmn:
add esp, 20 ; CF=0
pop esi
ret 4
 
;----------------------------------------------------------------
; fat_Read - FAT16/32 implementation of reading a file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Read:
call fat_lock
push edi
cmp byte [esi], 0
jnz @f
.noaccess:
pop edi
.noaccess_2:
call fat_unlock
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
 
@@:
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push eax
call fat_unlock
pop eax
or ebx, -1
ret
 
.found:
test byte [edi+11], 0x10; do not allow read directories
jnz .noaccess
cmp dword [ebx+8], 0
jz @f
xor ebx, ebx
.reteof:
call fat_unlock
mov eax, ERROR_END_OF_FILE
pop edi
ret
@@:
mov ecx, [ebx+12] ; size
mov edx, [ebx+16] ; pointer
mov ebx, [ebx+4] ; file offset
push edx
push 0
mov eax, [edi+28]
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
mov byte [esp], 6
@@:
mov eax, [edi+20-2]
mov ax, [edi+26]
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
.new_cluster:
jecxz .new_sector
cmp eax, 2
jb .eof
cmp eax, [ebp+FAT.fatRESERVED]
jae .eof
mov [ebp+FAT.cluster_tmp], eax
dec eax
dec eax
mov edi, [ebp+FAT.SECTORS_PER_CLUSTER]
imul eax, edi
add eax, [ebp+FAT.DATA_START]
.new_sector:
test ecx, ecx
jz .done
sub ebx, 512
jae .skip
add ebx, 512
jnz .force_buf
cmp ecx, 512
jb .force_buf
; we may read directly to given buffer
push eax ebx
mov ebx, edx
call fs_read32_app
test eax, eax
pop ebx eax
jne .noaccess_1
add edx, 512
sub ecx, 512
jmp .skip
.force_buf:
; we must read sector to temporary buffer and then copy it to destination
push eax ebx
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
test eax, eax
mov eax, ebx
pop ebx
jne .noaccess_3
add eax, ebx
push ecx
add ecx, ebx
cmp ecx, 512
jbe @f
mov ecx, 512
@@:
sub ecx, ebx
mov ebx, edx
call memmove
add edx, ecx
sub [esp], ecx
pop ecx
pop eax
xor ebx, ebx
.skip:
inc eax
dec edi
jnz .new_sector
mov eax, [ebp+FAT.cluster_tmp]
call get_FAT
jc .noaccess_1
 
jmp .new_cluster
.noaccess_3:
pop eax
.noaccess_1:
pop eax
push ERROR_DEVICE
.done:
mov ebx, edx
call fat_unlock
pop eax edx edi
sub ebx, edx
ret
.eof:
mov ebx, edx
pop eax edx
sub ebx, edx
jmp .reteof
 
;----------------------------------------------------------------
; fat_ReadFolder - FAT16/32 implementation of reading a folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_ReadFolder:
call fat_lock
mov eax, [ebp+FAT.ROOT_CLUSTER]
push edi
cmp byte [esi], 0
jz .doit
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push eax
call fat_unlock
pop eax
or ebx, -1
ret
.found:
test byte [edi+11], 0x10 ; do not allow read files
jnz .found_dir
pop edi
call fat_unlock
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
.found_dir:
mov eax, [edi+20-2]
mov ax, [edi+26] ; eax=cluster
.doit:
push esi
sub esp, 262*2 ; reserve space for LFN
push dword [ebx+8] ; for fat_get_name: read ANSI/UNICODE name
mov edx, [ebx+16] ; pointer to buffer
; init header
push eax
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
pop eax
mov byte [edx], 1 ; version
mov esi, edi ; esi points to BDFE
mov ecx, [ebx+12] ; number of blocks to read
mov ebx, [ebx+4] ; index of the first block
.new_cluster:
mov [ebp+FAT.cluster_tmp], eax
test eax, eax
jnz @f
cmp [ebp+FAT.fs_type], 32
jz .notfound
mov eax, [ebp+FAT.ROOT_START]
push [ebp+FAT.ROOT_SECTORS]
push ebx
jmp .new_sector
@@:
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
push [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
push ebx
.new_sector:
lea ebx, [ebp+FAT.buffer]
mov edi, ebx
push eax
call fs_read32_sys
test eax, eax
pop eax
jnz .notfound2
add ebx, 512
push eax
.l1:
push ebp
lea ebp, [esp+20]
call fat_get_name
pop ebp
jc .l2
cmp byte [edi+11], 0xF
jnz .do_bdfe
add edi, 0x20
cmp edi, ebx
jb .do_bdfe
pop eax
inc eax
dec dword [esp+4]
jnz @f
mov eax, [ebp+FAT.cluster_tmp]
test eax, eax
jz .done
call get_FAT
jc .notfound2
cmp eax, 2
jb .done
cmp eax, [ebp+FAT.fatRESERVED]
jae .done
push eax
mov eax, [ebp+FAT.SECTORS_PER_CLUSTER]
mov [esp+8], eax
pop eax
mov [ebp+FAT.cluster_tmp], eax
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
@@:
lea ebx, [ebp+FAT.buffer]
mov edi, ebx
push eax
call fs_read32_sys
test eax, eax
pop eax
jnz .notfound2
add ebx, 512
push eax
.do_bdfe:
inc dword [edx+8] ; new file found
dec dword [esp+4]
jns .l2
dec ecx
js .l2
inc dword [edx+4] ; new file block copied
push ebp
lea ebp, [esp+20]
call fat_entry_to_bdfe
pop ebp
.l2:
add edi, 0x20
cmp edi, ebx
jb .l1
pop eax
inc eax
dec dword [esp+4]
jnz .new_sector
mov eax, [ebp+FAT.cluster_tmp]
test eax, eax
jz .done
call get_FAT
jc .notfound2
cmp eax, 2
jb .done
cmp eax, [ebp+FAT.fatRESERVED]
jae .done
push eax
mov eax, [ebp+FAT.SECTORS_PER_CLUSTER]
mov [esp+8], eax
pop eax
pop ebx
add esp, 4
jmp .new_cluster
.notfound2:
add esp, 8
.notfound:
add esp, 262*2+4
pop esi edi
mov ebx, [edx+4]
call fat_unlock
mov eax, ERROR_DEVICE
ret
.done:
add esp, 262*2+4+8
mov ebx, [edx+4]
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
push eax
call fat_unlock
pop eax
pop esi edi
ret
 
fat16_root_next:
push ecx
lea ecx, [ebp+FAT.buffer+0x200-0x20]
cmp edi, ecx
jae fat16_root_next_sector
pop ecx
add edi, 0x20
ret ; CF=0
fat16_root_next_sector:
; read next sector
push [ebp+FAT.longname_sec2]
pop [ebp+FAT.longname_sec1]
mov ecx, [eax+4]
push ecx
add ecx, [ebp+FAT.ROOT_START]
mov [ebp+FAT.longname_sec2], ecx
pop ecx
inc ecx
mov [eax+4], ecx
cmp ecx, [ebp+FAT.ROOT_SECTORS]
pop ecx
jb fat16_root_first
mov eax, ERROR_FILE_NOT_FOUND
stc
ret
fat16_root_first:
mov eax, [eax+4]
add eax, [ebp+FAT.ROOT_START]
push ebx
lea edi, [ebp+FAT.buffer]
mov ebx, edi
call fs_read32_sys
pop ebx
test eax, eax
jnz .readerr
ret ; CF=0
.readerr:
mov eax, ERROR_DEVICE
stc
ret
.notfound:
mov eax, ERROR_FILE_NOT_FOUND
stc
ret
fat16_root_begin_write:
push edi eax
call fat16_root_first
pop eax edi
ret
fat16_root_end_write:
pusha
mov eax, [eax+4]
add eax, [ebp+FAT.ROOT_START]
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
popa
ret
fat16_root_next_write:
push ecx
lea ecx, [ebp+FAT.buffer+0x200]
cmp edi, ecx
jae @f
pop ecx
ret
@@:
call fat16_root_end_write
jmp fat16_root_next_sector
fat16_root_extend_dir:
stc
ret
 
fat_notroot_next:
push ecx
lea ecx, [ebp+FAT.buffer+0x200-0x20]
cmp edi, ecx
jae fat_notroot_next_sector
pop ecx
add edi, 0x20
ret ; CF=0
fat_notroot_next_sector:
push [ebp+FAT.longname_sec2]
pop [ebp+FAT.longname_sec1]
push eax
call fat_get_sector
mov [ebp+FAT.longname_sec2], eax
pop eax
mov ecx, [eax+4]
inc ecx
cmp ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
jae fat_notroot_next_cluster
mov [eax+4], ecx
jmp @f
fat_notroot_next_cluster:
push eax
mov eax, [eax]
call get_FAT
mov ecx, eax
pop eax
jc fat_notroot_first.deverr
cmp ecx, 2
jb fat_notroot_next_err
cmp ecx, [ebp+FAT.fatRESERVED]
jae fat_notroot_next_err
mov [eax], ecx
and dword [eax+4], 0
@@:
pop ecx
fat_notroot_first:
call fat_get_sector
push ebx
lea edi, [ebp+FAT.buffer]
mov ebx, edi
call fs_read32_sys
pop ebx
test eax, eax
jz .ret ; CF=0
push ecx
.deverr:
pop ecx
mov eax, ERROR_DEVICE
stc
.ret:
ret
fat_notroot_next_err:
pop ecx
mov eax, ERROR_FILE_NOT_FOUND
stc
ret
fat_notroot_begin_write:
push eax edi
call fat_notroot_first
pop edi eax
ret
fat_notroot_end_write:
call fat_get_sector
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
ret
fat_notroot_next_write:
push ecx
lea ecx, [ebp+FAT.buffer+0x200]
cmp edi, ecx
jae @f
pop ecx
ret
@@:
push eax
call fat_notroot_end_write
pop eax
jmp fat_notroot_next_sector
fat_notroot_extend_dir:
push eax
call get_free_FAT
jnc .found
pop eax
ret ; CF=1
.found:
push edx
mov edx, [ebp+FAT.fatEND]
call set_FAT
jc .writeerr
mov edx, eax
mov eax, [esp+4]
mov eax, [eax]
push edx
call set_FAT
pop edx
jnc @f
.writeerr:
pop edx
pop eax
stc
ret
@@:
push ecx
or ecx, -1
call add_disk_free_space
; zero new cluster
mov ecx, 512/4
lea edi, [ebp+FAT.buffer]
push edi
xor eax, eax
rep stosd
pop edi
pop ecx
mov eax, [esp+4]
mov [eax], edx
and dword [eax+4], 0
pop edx
mov eax, [eax]
dec eax
dec eax
push ebx ecx
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
imul eax, ecx
add eax, [ebp+FAT.DATA_START]
mov ebx, edi
@@:
push eax
call fs_write32_sys
pop eax
inc eax
loop @b
pop ecx ebx eax
clc
ret
 
fat_get_sector:
push ecx
mov ecx, [eax]
dec ecx
dec ecx
imul ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
add ecx, [ebp+FAT.DATA_START]
add ecx, [eax+4]
mov eax, ecx
pop ecx
ret
 
fshrad:
call fat_unlock
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
 
;----------------------------------------------------------------
; fat_CreateFolder - FAT16/32 implementation of creating a folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_CreateFolder:
push 1
jmp fat_Rewrite.common
 
;----------------------------------------------------------------
; fat_Rewrite - FAT16/32 implementation of creating a new file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Rewrite:
push 0
.common:
call fat_lock
pop eax
cmp byte [esi], 0
jz fshrad
mov ecx, [ebx+12]
mov edx, [ebx+16]
pushad
xor edi, edi
mov edx, [esp+4+20h]
push esi
test edx, edx
jz @f
mov esi, edx
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
lea edi, [esi-1]
jmp @b
@@:
pop esi
test edi, edi
jnz .noroot
test edx, edx
jnz .hasebp
mov edx, [ebp+FAT.ROOT_CLUSTER]
cmp [ebp+FAT.fs_type], 32
jz .pushnotroot
xor edx, edx
push edx
push fat16_root_extend_dir
push fat16_root_end_write
push fat16_root_next_write
push fat16_root_begin_write
push edx
push edx
push fat16_root_first
push fat16_root_next
jmp .common1
.hasebp:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edx], 0
jz .ret1
stdcall hd_find_lfn, 0
mov esi, [esp+4+20h]
jc .ret1
jmp .common0
.noroot:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edi+1], 0
jz .ret1
; check existence
mov byte [edi], 0
push edi
stdcall hd_find_lfn, [esp+4+24h]
pop esi
mov byte [esi], '/'
jnc @f
.notfound0:
mov eax, ERROR_FILE_NOT_FOUND
.ret1:
mov [esp+28], eax
call fat_unlock
popad
xor ebx, ebx
ret
@@:
inc esi
.common0:
test byte [edi+11], 0x10 ; must be directory
mov eax, ERROR_ACCESS_DENIED
jz .ret1
mov edx, [edi+20-2]
mov dx, [edi+26] ; ebp=cluster
mov eax, ERROR_FAT_TABLE
cmp edx, 2
jb .ret1
.pushnotroot:
push edx
push fat_notroot_extend_dir
push fat_notroot_end_write
push fat_notroot_next_write
push fat_notroot_begin_write
push 0
push edx
push fat_notroot_first
push fat_notroot_next
.common1:
call fat_find_lfn
jc .notfound
; found
test byte [edi+11], 10h
jz .exists_file
; found directory; if we are creating directory, return OK,
; if we are creating file, say "access denied"
add esp, 36
call fat_unlock
popad
test al, al
mov eax, ERROR_ACCESS_DENIED
jz @f
mov al, 0
@@:
xor ebx, ebx
ret
.exists_file:
; found file; if we are creating directory, return "access denied",
; if we are creating file, delete existing file and continue
cmp byte [esp+36+28], 0
jz @f
add esp, 36
call fat_unlock
popad
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
@@:
; delete FAT chain
push edi
xor eax, eax
mov dword [edi+28], eax ; zero size
xor ecx, ecx
mov eax, [edi+20-2]
mov ax, [edi+26]
mov word [edi+20], cx
mov word [edi+26], cx
test eax, eax
jz .done1
@@:
cmp eax, [ebp+FAT.fatRESERVED]
jae .done1
push edx
xor edx, edx
call set_FAT
mov eax, edx
pop edx
jc .done1
inc ecx
jmp @b
.done1:
pop edi
call get_time_for_file
mov [edi+22], ax
call get_date_for_file
mov [edi+24], ax
mov [edi+18], ax
or byte [edi+11], 20h ; set 'archive' attribute
jmp .doit
.notfound:
; file is not found; generate short name
call fat_name_is_legal
jc @f
add esp, 36
call fat_unlock
popad
mov eax, ERROR_FILE_NOT_FOUND
xor ebx, ebx
ret
@@:
sub esp, 12
mov edi, esp
call fat_gen_short_name
.test_short_name_loop:
push esi edi ecx
mov esi, edi
lea eax, [esp+12+12+8]
mov edx, [eax+24]
mov [eax], edx
and dword [eax+4], 0
call dword [eax-4]
jc .found
.test_short_name_entry:
cmp byte [edi+11], 0xF
jz .test_short_name_cont
mov ecx, 11
push esi edi
repz cmpsb
pop edi esi
jz .short_name_found
.test_short_name_cont:
lea eax, [esp+12+12+8]
call dword [eax-8]
jnc .test_short_name_entry
jmp .found
.short_name_found:
pop ecx edi esi
call fat_next_short_name
jnc .test_short_name_loop
.disk_full:
add esp, 12+36
call fat_unlock
popa
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.found:
pop ecx edi esi
; now find space in directory
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
mov al, '~'
push ecx edi
mov ecx, 8
repnz scasb
movi eax, 1 ; 1 entry
jnz .notilde
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
xor eax, eax
@@:
cmp byte [esi], 0
jz @f
inc esi
inc eax
jmp @b
@@:
sub esi, eax
add eax, 12+13
mov ecx, 13
push edx
cdq
div ecx
pop edx
.notilde:
push -1
push -1
push -1
; find <eax> successive entries in directory
xor ecx, ecx
push eax
lea eax, [esp+16+8+12+8]
mov edx, [eax+24]
mov [eax], edx
and dword [eax+4], 0
call dword [eax-4]
pop eax
jnc .scan_dir
.fsfrfe3:
add esp, 12+8+12+36
call fat_unlock
popad
mov eax, ERROR_DEVICE
xor ebx, ebx
ret
.scan_dir:
cmp byte [edi], 0
jz .free
cmp byte [edi], 0xE5
jz .free
xor ecx, ecx
.scan_cont:
push eax
lea eax, [esp+16+8+12+8]
call dword [eax-8]
mov edx, eax
pop eax
jnc .scan_dir
cmp edx, ERROR_DEVICE
jz .fsfrfe3
push eax
lea eax, [esp+16+8+12+8]
call dword [eax+20] ; extend directory
pop eax
jnc .scan_dir
add esp, 12+8+12+36
call fat_unlock
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.free:
test ecx, ecx
jnz @f
mov [esp], edi
mov ecx, [esp+12+8+12+8]
mov [esp+4], ecx
mov ecx, [esp+12+8+12+12]
mov [esp+8], ecx
xor ecx, ecx
@@:
inc ecx
cmp ecx, eax
jb .scan_cont
; found!
push esi ecx
; If creating a directory, allocate one data cluster now and fail immediately
; if this is impossible. This prevents from creating an invalid directory entry
; on a full disk.
; yup, the argument is quite non-intuitive... but what should I do if
; the entire function uses such arguments? BTW, it refers to al from pushad,
; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
cmp byte [esp+8+12+8+12+36+28], 0
jz .no.preallocate.folder.data
call get_free_FAT
jnc @f
add esp, 8+12+8
jmp .disk_full
@@:
mov [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
.no.preallocate.folder.data:
; calculate name checksum
mov esi, [esp+8+12]
mov ecx, 11
xor eax, eax
@@:
ror al, 1
add al, [esi]
inc esi
loop @b
pop ecx esi
pop edi
pop dword [esp+8+12+12]
pop dword [esp+8+12+12]
; edi points to first entry in free chunk
dec ecx
jz .nolfn
push esi
push eax
lea eax, [esp+8+8+12+8]
call dword [eax+8] ; begin write
mov al, 40h
.writelfn:
or al, cl
mov esi, [esp+4]
push ecx
dec ecx
imul ecx, 13
add esi, ecx
stosb
mov cl, 5
call fs_RamdiskRewrite.read_symbols
mov ax, 0xF
stosw
mov al, [esp+4]
stosb
mov cl, 6
call fs_RamdiskRewrite.read_symbols
xor eax, eax
stosw
mov cl, 2
call fs_RamdiskRewrite.read_symbols
pop ecx
lea eax, [esp+8+8+12+8]
call dword [eax+12] ; next write
xor eax, eax
loop .writelfn
pop eax
pop esi
; lea eax, [esp+8+12+8]
; call dword [eax+16] ; end write
.nolfn:
xchg esi, [esp]
mov ecx, 11
rep movsb
mov word [edi], 20h ; attributes
sub edi, 11
pop esi ecx
add esp, 12
mov byte [edi+13], 0 ; tenths of a second at file creation time
call get_time_for_file
mov [edi+14], ax ; creation time
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+16], ax ; creation date
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
xor ecx, ecx
mov word [edi+20], cx ; high word of cluster
mov word [edi+26], cx ; low word of cluster - to be filled
mov dword [edi+28], ecx ; file size - to be filled
cmp byte [esp+36+28], cl
jz .doit
; create directory
mov byte [edi+11], 10h ; attributes: folder
mov esi, edi
lea eax, [esp+8]
call dword [eax+16] ; flush directory
mov eax, [esp+36+20] ; extract saved cluster
mov [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
push ecx
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
shl ecx, 9
push ecx
push edi
jmp .doit2
.doit:
mov esi, [esp+36+20]
lea eax, [esp+8]
call dword [eax+16] ; flush directory
push ecx
mov ecx, [esp+4+36+24]
push ecx
push edi
test ecx, ecx
jz .done
call get_free_FAT
jc .diskfull
.doit2:
push eax
mov [edi+26], ax
shr eax, 16
mov [edi+20], ax
lea eax, [esp+16+8]
call dword [eax+16] ; flush directory
pop eax
push edx
mov edx, [ebp+FAT.fatEND]
call set_FAT
pop edx
.write_cluster:
push eax
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
push [ebp+FAT.SECTORS_PER_CLUSTER]
; write data
.write_sector:
cmp byte [esp+20+36+28], 0
jnz .writedir
mov ecx, 512
cmp dword [esp+12], ecx
jb .writeshort
; we can write directly from given buffer
mov ebx, esi
add esi, ecx
jmp .writecommon
.writeshort:
mov ecx, [esp+12]
push ecx
lea edi, [ebp+FAT.buffer]
mov ebx, edi
rep movsb
.writedircont:
lea ecx, [ebp+FAT.buffer+0x200]
sub ecx, edi
push eax
xor eax, eax
rep stosb
pop eax
pop ecx
.writecommon:
push eax
call fs_write32_app
test eax, eax
pop eax
jnz .writeerr
inc eax
sub dword [esp+12], ecx
jz .writedone
dec dword [esp]
jnz .write_sector
pop eax
; allocate new cluster
pop eax
mov ecx, eax
call get_free_FAT
jc .diskfull
push edx
mov edx, [ebp+FAT.fatEND]
call set_FAT
xchg eax, ecx
mov edx, ecx
call set_FAT
pop edx
xchg eax, ecx
jmp .write_cluster
.diskfull:
mov eax, ERROR_DISK_FULL
jmp .ret
.writeerr:
pop eax eax
sub esi, ecx
mov eax, ERROR_DEVICE
jmp .ret
.writedone:
pop eax eax
.done:
xor eax, eax
.ret:
pop edi ecx
sub esi, [esp+4+36+20]
mov [esp+4+36+28], eax
mov [esp+4+36+16], esi
lea eax, [esp+12]
call dword [eax+8]
mov [edi+28], esi
call dword [eax+16]
mov [esp+36+16], ebx
lea eax, [esi+511]
shr eax, 9
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
lea eax, [eax+ecx-1]
xor edx, edx
div ecx
pop ecx
sub ecx, eax
call add_disk_free_space
add esp, 36
call update_disk
call fat_unlock
popad
ret
.writedir:
push 512
lea edi, [ebp+FAT.buffer]
mov ebx, edi
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
shl ecx, 9
cmp ecx, [esp+16]
jnz .writedircont
dec dword [esp+20]
push esi
mov ecx, 32/4
rep movsd
pop esi
mov dword [edi-32], '. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
push esi
mov ecx, 32/4
rep movsd
pop esi
mov dword [edi-32], '.. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov ecx, [esp+20+36]
cmp ecx, [ebp+FAT.ROOT_CLUSTER]
jnz @f
xor ecx, ecx
@@:
mov word [edi-32+26], cx
shr ecx, 16
mov [edi-32+20], cx
jmp .writedircont
 
fat_Write.access_denied:
push ERROR_ACCESS_DENIED
fat_Write.ret0:
pop eax
xor ebx, ebx
ret
 
fat_Write.ret11:
push ERROR_DEVICE
jmp fat_Write.ret0
 
;----------------------------------------------------------------
; fat_Write - FAT16/32 implementation of writing to file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Write:
cmp byte [esi], 0
jz .access_denied
call fat_lock
push edi
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push eax
call fat_unlock
jmp .ret0
.found:
; FAT does not support files larger than 4GB
cmp dword [ebx+8], 0
jz @f
.eof:
pop edi
push ERROR_END_OF_FILE
call fat_unlock
jmp .ret0
@@:
mov ecx, [ebx+12]
mov edx, [ebx+16]
mov ebx, [ebx+4]
; now edi points to direntry, ebx=start byte to write,
; ecx=number of bytes to write, edx=data pointer
 
; extend file if needed
add ecx, ebx
jc .eof ; FAT does not support files larger than 4GB
push edx
push eax ; save directory sector
push 0 ; return value=0
 
call get_time_for_file
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
 
push dword [edi+28] ; save current file size
cmp ecx, [edi+28]
jbe .length_ok
cmp ecx, ebx
jz .length_ok
call hd_extend_file
jnc .length_ok
mov [esp+4], eax
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
; First two cases are fatal errors, in third case we may write some data
cmp al, ERROR_DISK_FULL
jz .disk_full
call fat_unlock
pop eax
pop eax
pop ecx
pop edx
pop edi
xor ebx, ebx
ret
.disk_full:
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
push 0
.ret:
pop eax
sub edx, [esp+12]
mov ebx, edx ; ebx=number of written bytes
call update_disk
test eax, eax
jz @f
mov byte [esp+4], ERROR_DEVICE
@@:
call fat_unlock
pop eax
pop eax
pop ecx
pop edx
pop edi
ret
.length_ok:
mov esi, [edi+28]
mov eax, [edi+20-2]
mov ax, [edi+26]
mov edi, eax ; edi=current cluster
push 0 ; current sector in cluster
; save directory
mov eax, [esp+12]
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
test eax, eax
jz @f
.device_err:
mov byte [esp+8], ERROR_DEVICE
jmp .ret
.fat_err:
mov byte [esp+8], ERROR_FAT_TABLE
jmp .ret
@@:
 
; now ebx=start pos, ecx=end pos, both lie inside file
sub ecx, ebx
jz .ret
.write_loop:
; skip unmodified sectors
cmp dword [esp+4], 0x200
jb .modify
sub ebx, 0x200
jae .skip
add ebx, 0x200
.modify:
; get length of data in current sector
push ecx
sub ebx, 0x200
jb .hasdata
neg ebx
xor ecx, ecx
jmp @f
.hasdata:
neg ebx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
; get current sector number
mov eax, edi
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
add eax, [esp+4]
; load sector if needed
cmp dword [esp+8], 0 ; we don't need to read uninitialized data
jz .noread
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten
jz .noread
cmp ecx, esi ; (same for the last sector)
jz .noread
push eax ebx
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
test eax, eax
pop ebx eax
jz @f
.device_err2:
pop ecx
jmp .device_err
@@:
.noread:
; zero uninitialized data if file was extended (because hd_extend_file does not this)
push eax ecx edi
xor eax, eax
mov ecx, 0x200
sub ecx, [esp+8+12]
jbe @f
lea edi, [ebp+FAT.buffer]
add edi, [esp+8+12]
rep stosb
@@:
; zero uninitialized data in the last sector
mov ecx, 0x200
sub ecx, esi
jbe @f
lea edi, [ebp+FAT.buffer+esi]
rep stosb
@@:
pop edi ecx
; copy new data
mov eax, edx
neg ebx
jecxz @f
lea ebx, [ebp+FAT.buffer+0x200+ebx]
call memmove
xor ebx, ebx
@@:
pop eax
; save sector
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_app
pop ebx
test eax, eax
jnz .device_err2
add edx, ecx
sub [esp], ecx
pop ecx
jz .ret
.skip:
; next sector
pop eax
inc eax
push eax
cmp eax, [ebp+FAT.SECTORS_PER_CLUSTER]
jb @f
and dword [esp], 0
mov eax, edi
call get_FAT
mov edi, eax
jc .device_err
cmp edi, 2
jb .fat_err
cmp edi, [ebp+FAT.fatRESERVED]
jae .fat_err
@@:
sub esi, 0x200
jae @f
xor esi, esi
@@:
sub dword [esp+4], 0x200
jae @f
and dword [esp+4], 0
@@:
jmp .write_loop
 
hd_extend_file.zero_size:
xor eax, eax
jmp hd_extend_file.start_extend
 
; extends file on hd to given size (new data area is undefined)
; in: edi->direntry, ecx=new size
; out: CF=0 => OK, eax=0
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
hd_extend_file:
push esi
mov esi, [ebp+FAT.SECTORS_PER_CLUSTER]
imul esi, [ebp+FAT.BYTES_PER_SECTOR]
push ecx
; find the last cluster of file
mov eax, [edi+20-2]
mov ax, [edi+26]
mov ecx, [edi+28]
jecxz .zero_size
.last_loop:
sub ecx, esi
jbe .last_found
call get_FAT
jnc @f
.device_err:
pop ecx
.device_err2:
pop esi
push ERROR_DEVICE
.ret_err:
pop eax
stc
ret
@@:
cmp eax, 2
jb .fat_err
cmp eax, [ebp+FAT.fatRESERVED]
jb .last_loop
.fat_err:
pop ecx esi
push ERROR_FAT_TABLE
jmp .ret_err
.last_found:
push eax
call get_FAT
jnc @f
pop eax
jmp .device_err
@@:
cmp eax, [ebp+FAT.fatRESERVED]
pop eax
jb .fat_err
; set length to full number of clusters
sub [edi+28], ecx
.start_extend:
pop ecx
; now do extend
push edx
mov edx, 2 ; start scan from cluster 2
.extend_loop:
cmp [edi+28], ecx
jae .extend_done
; add new cluster
push eax
call get_free_FAT
jc .disk_full
mov edx, [ebp+FAT.fatEND]
call set_FAT
mov edx, eax
pop eax
test eax, eax
jz .first_cluster
push edx
call set_FAT
pop edx
jmp @f
.first_cluster:
ror edx, 16
mov [edi+20], dx
ror edx, 16
mov [edi+26], dx
@@:
push ecx
mov ecx, -1
call add_disk_free_space
pop ecx
mov eax, edx
add [edi+28], esi
jmp .extend_loop
.extend_done:
mov [edi+28], ecx
pop edx esi
xor eax, eax ; CF=0
ret
.device_err3:
pop edx
jmp .device_err2
.disk_full:
pop eax edx esi
movi eax, ERROR_DISK_FULL
stc
ret
 
;----------------------------------------------------------------
; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_SetFileEnd:
call fat_lock
push edi
cmp byte [esi], 0
jnz @f
.access_denied:
push ERROR_ACCESS_DENIED
.ret:
call fat_unlock
pop eax
pop edi
ret
@@:
stdcall hd_find_lfn, [esp+4+4]
jnc @f
.reteax:
push eax
jmp .ret
@@:
; must not be directory
test byte [edi+11], 10h
jnz .access_denied
; file size must not exceed 4 Gb
cmp dword [ebx+8], 0
jz @f
push ERROR_END_OF_FILE
jmp .ret
@@:
push eax ; save directory sector
; set file modification date/time to current
call fat_update_datetime
mov eax, [ebx+4]
cmp eax, [edi+28]
jb .truncate
ja .expand
pop eax
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
test eax, eax
jz @f
push ERROR_DEVICE
jmp .ret
@@:
push 0
jmp .ret
.expand:
push ebx ebp ecx
push dword [edi+28] ; save old size
mov ecx, eax
call hd_extend_file
push eax ; return code
jnc .expand_ok
cmp al, ERROR_DISK_FULL
jz .disk_full
.pop_ret:
call update_disk
pop eax ecx ecx ebp ebx ecx
jmp .reteax
.expand_ok:
.disk_full:
; save directory
mov eax, [edi+28]
xchg eax, [esp+20]
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
test eax, eax
mov eax, [edi+20-2]
mov ax, [edi+26]
mov edi, eax
jz @f
.pop_ret11:
mov byte [esp], ERROR_DEVICE
jmp .pop_ret
@@:
test edi, edi
jz .pop_ret
; now zero new data
push 0
; edi=current cluster, [esp]=sector in cluster
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
.zero_loop:
cmp edi, 2
jb .error_fat
cmp edi, [ebp+FAT.fatRESERVED]
jae .error_fat
sub dword [esp+8], 0x200
jae .next_cluster
lea eax, [edi-2]
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
add eax, [esp]
cmp dword [esp+8], -0x200
jz .noread
push eax
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
test eax, eax
pop eax
jnz .err_next
.noread:
mov ecx, [esp+8]
neg ecx
push edi
lea edi, [ebp+FAT.buffer+0x200]
add edi, [esp+12]
push eax
xor eax, eax
mov [esp+16], eax
rep stosb
pop eax
pop edi
call fs_write32_app
test eax, eax
jz .next_cluster
.err_next:
mov byte [esp+4], ERROR_DEVICE
.next_cluster:
pop eax
sub dword [esp+20], 0x200
jbe .pop_ret
inc eax
push eax
cmp eax, [ebp+FAT.SECTORS_PER_CLUSTER]
jb .zero_loop
and dword [esp], 0
mov eax, edi
call get_FAT
mov edi, eax
jnc .zero_loop
pop eax
jmp .pop_ret11
.truncate:
mov [edi+28], eax
push ecx
mov ecx, [edi+20-2]
mov cx, [edi+26]
push eax
test eax, eax
jz .zero_size
; find new last cluster
@@:
cmp ecx, 2
jb .error_fat2
cmp ecx, [ebp+FAT.fatRESERVED]
jae .error_fat2
mov eax, [ebp+FAT.SECTORS_PER_CLUSTER]
shl eax, 9
sub [esp], eax
jbe @f
mov eax, ecx
call get_FAT
mov ecx, eax
jnc @b
.device_err3:
pop eax ecx eax edi
call update_disk
call fat_unlock
movi eax, ERROR_DEVICE
ret
@@:
; we will zero data at the end of last sector - remember it
push ecx
; terminate FAT chain
push edx
mov eax, ecx
mov edx, [ebp+FAT.fatEND]
call set_FAT
mov eax, edx
pop edx
jnc @f
.device_err4:
pop ecx
jmp .device_err3
.zero_size:
and word [edi+20], 0
and word [edi+26], 0
push 0
mov eax, ecx
@@:
; delete FAT chain
call clear_cluster_chain
jc .device_err4
; save directory
mov eax, [esp+12]
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
test eax, eax
jnz .device_err4
; zero last sector, ignore errors
pop ecx
pop eax
dec ecx
imul ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
add ecx, [ebp+FAT.DATA_START]
push eax
sar eax, 9
add ecx, eax
pop eax
and eax, 0x1FF
jz .truncate_done
push ebx eax
mov eax, ecx
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
pop eax
lea edi, [ebp+FAT.buffer+eax]
push ecx
mov ecx, 0x200
sub ecx, eax
xor eax, eax
rep stosb
pop eax
call fs_write32_app
pop ebx
.truncate_done:
pop ecx eax edi
call update_disk
call fat_unlock
xor eax, eax
ret
.error_fat:
pop eax
mov byte [esp], ERROR_FAT_TABLE
jmp .pop_ret
.error_fat2:
pop eax ecx eax edi
call update_disk
call fat_unlock
movi eax, ERROR_FAT_TABLE
ret
 
;----------------------------------------------------------------
; fat_GetFileInfo - FAT16/32 implementation of getting file info
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_GetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2
ret
@@:
push edi
call fat_lock
stdcall hd_find_lfn, [esp+4+4]
jc .error
push ebp
xor ebp, ebp
mov esi, [ebx+16]
mov dword [esi+4], ebp
call fat_entry_to_bdfe2
pop ebp
call fat_unlock
xor eax, eax
pop edi
ret
.error:
push eax
call fat_unlock
pop eax
pop edi
ret
 
;----------------------------------------------------------------
; fat_SetFileInfo - FAT16/32 implementation of setting file info
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_SetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2
ret
@@:
push edi
call fat_lock
stdcall hd_find_lfn, [esp+4+4]
jc .error
push eax
mov edx, [ebx+16]
call bdfe_to_fat_entry
pop eax
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
call update_disk
call fat_unlock
pop edi
xor eax, eax
ret
.error:
push eax
call fat_unlock
pop eax
pop edi
ret
 
;----------------------------------------------------------------
; fat_Delete - FAT16/32 implementation of deleting a file/folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Delete:
call fat_lock
cmp byte [esi], 0
jnz @f
; cannot delete root!
.access_denied:
push ERROR_ACCESS_DENIED
.pop_ret:
call fat_unlock
pop eax
xor ebx, ebx
ret
@@:
and [ebp+FAT.longname_sec1], 0
and [ebp+FAT.longname_sec2], 0
push edi
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push ERROR_FILE_NOT_FOUND
jmp .pop_ret
.found:
cmp dword [edi], '. '
jz .access_denied2
cmp dword [edi], '.. '
jz .access_denied2
test byte [edi+11], 10h
jz .dodel
; we can delete only empty folders!
pushad
mov esi, [edi+20-2]
mov si, [edi+26]
xor ecx, ecx
lea eax, [esi-2]
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
lea ebx, [ebp+FAT.buffer]
call fs_read32_sys
test eax, eax
jnz .err1
lea eax, [ebx+0x200]
add ebx, 2*0x20
.checkempty:
cmp byte [ebx], 0
jz .empty
cmp byte [ebx], 0xE5
jnz .notempty
add ebx, 0x20
cmp ebx, eax
jb .checkempty
inc ecx
cmp ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
jb @f
mov eax, esi
call get_FAT
jc .err1
cmp eax, 2
jb .error_fat
cmp eax, [ebp+FAT.fatRESERVED]
jae .empty
mov esi, eax
xor ecx, ecx
@@:
lea eax, [esi-2]
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
add eax, ecx
lea ebx, [ebp+FAT.buffer]
call fs_read32_sys
test eax, eax
lea eax, [ebx+0x200]
jz .checkempty
.err1:
popad
.err2:
pop edi
call fat_unlock
movi eax, ERROR_DEVICE
ret
.error_fat:
popad
pop edi
call fat_unlock
movi eax, ERROR_FAT_TABLE
ret
.notempty:
popad
.access_denied2:
pop edi
call fat_unlock
movi eax, ERROR_ACCESS_DENIED
ret
.empty:
popad
push eax ebx
lea ebx, [ebp+FAT.buffer]
call fs_read32_sys
test eax, eax
pop ebx eax
jnz .err2
.dodel:
push eax
mov eax, [edi+20-2]
mov ax, [edi+26]
xchg eax, [esp]
; delete folder entry
mov byte [edi], 0xE5
; delete LFN (if present)
.lfndel:
lea edx, [ebp+FAT.buffer]
cmp edi, edx
ja @f
cmp [ebp+FAT.longname_sec2], 0
jz .lfndone
push [ebp+FAT.longname_sec2]
push [ebp+FAT.longname_sec1]
pop [ebp+FAT.longname_sec2]
and [ebp+FAT.longname_sec1], 0
push ebx
mov ebx, edx
call fs_write32_sys
mov eax, [esp+4]
call fs_read32_sys
pop ebx
pop eax
lea edi, [ebp+FAT.buffer+0x200]
@@:
sub edi, 0x20
cmp byte [edi], 0xE5
jz .lfndone
cmp byte [edi+11], 0xF
jnz .lfndone
mov byte [edi], 0xE5
jmp .lfndel
.lfndone:
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
; delete FAT chain
pop eax
call clear_cluster_chain
call update_disk
call fat_unlock
pop edi
xor eax, eax
ret
 
; \end{diamond}
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/fs/fs_lfn.inc
30,6 → 30,18
iglobal
; in this table names must be in lowercase
rootdirs:
db 2,'rd'
dd fs_OnRamdisk
dd fs_NextRamdisk
db 7,'ramdisk'
dd fs_OnRamdisk
dd fs_NextRamdisk
db 2,'fd'
dd fs_OnFloppy
dd fs_NextFloppy
db 10,'floppydisk'
dd fs_OnFloppy
dd fs_NextFloppy
;**********************************************
db 3,'cd0'
dd fs_OnCd0
48,6 → 60,10
 
 
virtual_root_query:
dd fs_HasRamdisk
db 'rd',0
dd fs_HasFloppy
db 'fd',0
;**********************************************
dd fs_HasCd0
db 'cd0',0
59,6 → 75,12
db 'cd3',0
;**********************************************
dd 0
 
fs_additional_handlers:
dd dyndisk_handler, dyndisk_enum_root
; add new handlers here
dd 0
 
endg
 
file_system_lfn_protected:
235,6 → 257,7
 
.readroot:
; virtual root folder - special handler
mov esi, virtual_root_query
mov ebp, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
246,51 → 269,9
mov ecx, 32/4
rep stosd
mov byte [edx], 1 ; version
sub esp, 16
.readroot_ah_loop2:
push edi
lea edi, [esp+4]
call dyndisk_enum_root
pop edi
test eax, eax
jz .readroot_done_dynamic
inc dword [edx+8]
dec dword [esp+16]
jns .readroot_ah_loop2
dec ebp
js .readroot_ah_loop2
push eax
xor eax, eax
inc dword [edx+4]
mov dword [edi], 0x10 ; attributes: folder
mov dword [edi+4], ebx
add edi, 8
mov ecx, 40/4-2
rep stosd
push esi edi
lea esi, [esp+12]
@@:
lodsb
stosb
test bl, 1
jz .ansi3
mov byte [edi], 0
inc edi
.ansi3:
test al, al
jnz @b
pop edi esi eax
add edi, 520
test bl, 1
jnz .readroot_ah_loop2
sub edi, 520-264
jmp .readroot_ah_loop2
.readroot_done_dynamic:
add esp, 16
mov esi, virtual_root_query
.readroot_loop:
cmp dword [esi], eax
jz .readroot_done
jz .readroot_done_static
call dword [esi]
add esi, 4
test eax, eax
331,7 → 312,54
jnz .readroot_loop
sub edi, 520-264
jmp .readroot_loop
.readroot_done_static:
mov esi, fs_additional_handlers-8
sub esp, 16
.readroot_ah_loop:
add esi, 8
cmp dword [esi], 0
jz .readroot_done
xor eax, eax
.readroot_ah_loop2:
push edi
lea edi, [esp+4]
call dword [esi+4]
pop edi
test eax, eax
jz .readroot_ah_loop
inc dword [edx+8]
dec dword [esp+16]
jns .readroot_ah_loop2
dec ebp
js .readroot_ah_loop2
push eax
xor eax, eax
inc dword [edx+4]
mov dword [edi], 0x10 ; attributes: folder
mov dword [edi+4], ebx
add edi, 8
mov ecx, 40/4-2
rep stosd
push esi edi
lea esi, [esp+12]
@@:
lodsb
stosb
test bl, 1
jz .ansi3
mov byte [edi], 0
inc edi
.ansi3:
test al, al
jnz @b
pop edi esi eax
add edi, 520
test bl, 1
jnz .readroot_ah_loop2
sub edi, 520-264
jmp .readroot_ah_loop2
.readroot_done:
add esp, 16
pop eax
mov ebx, [edx+4]
xor eax, eax
343,7 → 371,14
mov [image_of_ebx], ebx
ret
.notfound_try:
call dyndisk_handler
mov edi, fs_additional_handlers
@@:
cmp dword [edi], 0
jz .notfound
call dword [edi]
scasd
scasd
jmp @b
.notfound:
mov dword [image_of_eax], ERROR_FILE_NOT_FOUND
and dword [image_of_ebx], 0
401,10 → 436,72
; ebp = 0 or pointer to rest of name from folder addressed by esi
; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
 
fs_OnRamdisk:
cmp ecx, 1
jnz file_system_lfn.notfound
mov eax, [ebx]
cmp eax, fs_NumRamdiskServices
jae .not_impl
mov ecx, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
add ebx, 4
call dword [fs_RamdiskServices + eax*4]
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
.not_impl:
mov dword [image_of_eax], 2 ; not implemented
ret
 
fs_NotImplemented:
mov eax, 2
ret
 
fs_RamdiskServices:
dd fs_RamdiskRead
dd fs_RamdiskReadFolder
dd fs_RamdiskRewrite
dd fs_RamdiskWrite
dd fs_RamdiskSetFileEnd
dd fs_RamdiskGetFileInfo
dd fs_RamdiskSetFileInfo
dd 0
dd fs_RamdiskDelete
dd fs_RamdiskCreateFolder
fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4
 
fs_OnFloppy:
cmp ecx, 2
ja file_system_lfn.notfound
mov eax, [ebx]
cmp eax, fs_NumFloppyServices
jae fs_OnRamdisk.not_impl
call reserve_flp
mov [flp_number], cl
mov ecx, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
add ebx, 4
call dword [fs_FloppyServices + eax*4]
and [flp_status], 0
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
 
fs_FloppyServices:
dd fs_FloppyRead
dd fs_FloppyReadFolder
dd fs_FloppyRewrite
dd fs_FloppyWrite
dd fs_FloppySetFileEnd
dd fs_FloppyGetFileInfo
dd fs_FloppySetFileInfo
dd 0
dd fs_FloppyDelete
dd fs_FloppyCreateFolder
fs_NumFloppyServices = ($ - fs_FloppyServices)/4
 
;*******************************************************
fs_OnCd0:
call reserve_cd
487,6 → 584,16
fs_NumCdServices = ($ - fs_CdServices)/4
 
;*******************************************************
 
fs_HasRamdisk:
mov al, 1 ; we always have ramdisk
ret
fs_HasFloppy:
cmp byte [DRIVE_DATA], 0
setnz al
ret
 
;*******************************************************
fs_HasCd0:
test byte [DRIVE_DATA+1], 10000000b
setnz al
510,6 → 617,36
; out: CF=1 => no more partitions
; CF=0 => eax=next partition number
 
fs_NextRamdisk:
; we always have /rd/1
test eax, eax
stc
jnz @f
mov al, 1
clc
@@:
ret
 
fs_NextFloppy:
; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0)
test byte [DRIVE_DATA], 0xF0
jz .no1
test eax, eax
jnz .no1
inc eax
ret ; CF cleared
.no1:
test byte [DRIVE_DATA], 0x0F
jz .no2
cmp al, 2
jae .no2
mov al, 2
clc
ret
.no2:
stc
ret
 
;*******************************************************
fs_NextCd:
; we always have /cdX/1
/kernel/branches/Kolibri-acpi/fs/part_set.inc
0,0 → 1,436
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
;*************************************************************
;* 13.02.2010 Find all partition and check supported FS
;* 12.07.2007 Check all 4 entry of MBR and EMBR
;* 29.04.2006 Elimination of hangup after the
;* expiration hd_wait_timeout - Mario79
;* 28.01.2006 find all Fat16/32 partition in all input point
;* to MBR - Mario79
;*************************************************************
 
uglobal
align 4
 
;******************************************************
; Please do not change this place - variables in text
; Mario79
; START place
;******************************************************
PARTITION_START dd 0x3f
PARTITION_END dd 0
fs_type db 0 ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32
align 4
 
fs_dependent_data_start:
; FATxx data
 
.partition dd ?
rb 80
 
fs_dependent_data_end:
file_system_data_size = $ - PARTITION_START
if file_system_data_size > 96
ERROR:
sizeof(file system data) too big!
end if
 
virtual at fs_dependent_data_start
; NTFS data
ntfs_data:
.sectors_per_cluster dd ?
.mft_cluster dd ?
.mftmirr_cluster dd ?
.frs_size dd ? ; FRS size in bytes
.iab_size dd ? ; IndexAllocationBuffer size in bytes
.frs_buffer dd ?
.iab_buffer dd ?
.mft_retrieval dd ?
.mft_retrieval_size dd ?
.mft_retrieval_alloc dd ?
.mft_retrieval_end dd ?
.cur_index_size dd ?
.cur_index_buf dd ?
if $ > fs_dependent_data_end
ERROR:
increase sizeof(fs_dependent_data)!
end if
end virtual
 
virtual at fs_dependent_data_start
; EXT2 data
ext2_data:
.log_block_size dd ?
.block_size dd ?
.count_block_in_block dd ?
.blocks_per_group dd ?
.global_desc_table dd ?
.root_inode dd ? ; pointer to root inode in memory
.inode_size dd ?
.count_pointer_in_block dd ? ; block_size / 4
.count_pointer_in_block_square dd ? ; (block_size / 4)**2
.ext2_save_block dd ? ;RUS: блок на глобальную 1 процедуру ;ENG: block for 1 global procedure
.ext2_temp_block dd ? ;RUS: блок для мелких процедур ;ENG: block for small procedures
.ext2_save_inode dd ? ;RUS: inode на глобальную процедуру ;ENG: inode for global procedure
.ext2_temp_inode dd ? ;RUS: inode для мелких процедур ;ENG: inode for small procedures
.sb dd ? ; superblock
.groups_count dd ?
if $ > fs_dependent_data_end
ERROR:
increase sizeof(fs_dependent_data)!
end if
end virtual
 
;***************************************************************************
; End place
; Mario79
;***************************************************************************
endg
iglobal
 
partition_types: ; list of fat16/32 partitions
db 0x04 ; DOS: fat16 <32M
db 0x06 ; DOS: fat16 >32M
db 0x0b ; WIN95: fat32
db 0x0c ; WIN95: fat32, LBA-mapped
db 0x0e ; WIN95: fat16, LBA-mapped
db 0x14 ; Hidden DOS: fat16 <32M
db 0x16 ; Hidden DOS: fat16 >32M
db 0x1b ; Hidden WIN95: fat32
db 0x1c ; Hidden WIN95: fat32, LBA-mapped
db 0x1e ; Hidden WIN95: fat16, LBA-mapped
db 0xc4 ; DRDOS/secured: fat16 <32M
db 0xc6 ; DRDOS/secured: fat16 >32M
db 0xcb ; DRDOS/secured: fat32
db 0xcc ; DRDOS/secured: fat32, LBA-mapped
db 0xce ; DRDOS/secured: fat16, LBA-mapped
db 0xd4 ; Old Multiuser DOS secured: fat16 <32M
db 0xd6 ; Old Multiuser DOS secured: fat16 >32M
db 0x07 ; NTFS
db 0x27 ; NTFS, hidden
db 0x83 ; Linux native file system (ext2fs)
partition_types_end:
 
 
extended_types: ; list of extended partitions
db 0x05 ; DOS: extended partition
db 0x0f ; WIN95: extended partition, LBA-mapped
db 0xc5 ; DRDOS/secured: extended partition
db 0xd5 ; Old Multiuser DOS secured: extended partition
extended_types_end:
 
endg
 
; Partition chain used:
; MBR <---------------------
; | |
; |-> PARTITION1 |
; |-> EXTENDED PARTITION - ;not need be second partition
; |-> PARTITION3
; |-> PARTITION4
 
set_PARTITION_variables:
set_FAT32_variables: ;deprecated
and [problem_partition], 0
call reserve_hd1
call reserve_hd_channel
 
pushad
 
cmp dword [hdpos], 0
je problem_hd
 
xor ecx, ecx ; partition count
;or edx,-1 ; flag for partition
xor eax, eax ; address MBR
xor ebp, ebp ; extended partition start
 
new_mbr:
test ebp, ebp ; is there extended partition? (MBR or EMBR)
jnz extended_already_set; yes
xchg ebp, eax ; no. set it now
 
extended_already_set:
add eax, ebp ; mbr=mbr+0, ext_part=ext_start+relat_start
mov ebx, buffer
call hd_read
cmp [hd_error], 0
jne problem_hd
 
cmp word [ebx+0x1fe], 0xaa55; is it valid boot sector?
jnz end_partition_chain
push eax ; push only one time
cmp dword [ebx+0x1be+0xc], 0; skip over empty partition
jnz test_primary_partition_0
cmp dword [ebx+0x1be+0xc+16], 0
jnz test_primary_partition_1
cmp dword [ebx+0x1be+0xc+16+16], 0
jnz test_primary_partition_2
cmp dword [ebx+0x1be+0xc+16+16+16], 0
jnz test_primary_partition_3
pop eax
jmp end_partition_chain
 
test_primary_partition_0:
mov al, [ebx+0x1be+4]; get primary partition type
call scan_partition_types
jnz test_primary_partition_1; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_primary_partition_1; no
 
pop eax
;mov edx, eax ; start sector
add eax, [ebx+0x1be+8] ; add relative start
;mov [PARTITON_START],edx
;push edx
mov edx, [ebx+0x1be+12] ; length
;add edx, eax ; add length
;dec edx ; PARTITION_END is inclusive
;mov [PARTITION_END], edx ; note that this can be changed
; when file system data will be available
mov cl, [ebx+0x1be+4] ; fs_type
;mov [fs_type], dl ; save for FS recognizer (separate FAT vs NTFS)
;pop edx
jmp hd_and_partition_ok
 
test_primary_partition_1:
mov al, [ebx+0x1be+4+16]; get primary partition type
call scan_partition_types
jnz test_primary_partition_2 ; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_primary_partition_2 ; no
 
pop eax
add eax, [ebx+0x1be+8+16]
mov edx, [ebx+0x1be+12+16]
mov cl, [ebx+0x1be+4+16]
jmp hd_and_partition_ok
 
;mov edx, eax
;add edx, [ebx+0x1be+8+16]
;push edx
;add edx, [ebx+0x1be+12+16]
;dec edx
;mov [PARTITION_END], edx
;mov al, [ebx+0x1be+4+16]
;mov [fs_type], dl
;pop edx
 
test_primary_partition_2:
mov al, [ebx+0x1be+4+16+16]; get primary partition type
call scan_partition_types
jnz test_primary_partition_3 ; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_primary_partition_3 ; no
 
pop eax
add eax, [ebx+0x1be+8+16+16]
mov edx, [ebx+0x1be+12+16+16]
mov cl, [ebx+0x1be+4+16+16]
jmp hd_and_partition_ok
;mov edx, eax
;add edx, [ebx+0x1be+8+16+16]
;push edx
;add edx, [ebx+0x1be+12+16+16]
;dec edx
;mov [PARTITION_END], edx
;mov al, [ebx+0x1be+4+16+16]
;mov [fs_type], dl
;pop edx
 
test_primary_partition_3:
mov al, [ebx+0x1be+4+16+16+16]; get primary partition type
call scan_partition_types
jnz test_ext_partition_0 ; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_ext_partition_0; no
 
pop eax
add eax, [ebx+0x1be+8+16+16+16]
mov edx, [ebx+0x1be+12+16+16+16]
mov cl, [ebx+0x1be+4+16+16+16]
jmp hd_and_partition_ok
 
;mov edx, eax
;add edx, [ebx+0x1be+8+16+16+16]
;push edx
;add edx, [ebx+0x1be+12+16+16+16]
;dec edx
;mov [PARTITION_END], edx
;mov al, [ebx+0x1be+4+16+16+16]
;mov [fs_type], dl
;pop edx
 
test_ext_partition_0:
pop eax ; просто выкидываем из стека
mov al, [ebx+0x1be+4]; get extended partition type
call scan_extended_types
jnz test_ext_partition_1
 
mov eax, [ebx+0x1be+8]; add relative start
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
test_ext_partition_1:
mov al, [ebx+0x1be+4+16]; get extended partition type
call scan_extended_types
jnz test_ext_partition_2
 
mov eax, [ebx+0x1be+8+16]; add relative start
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
test_ext_partition_2:
mov al, [ebx+0x1be+4+16+16]; get extended partition type
call scan_extended_types
jnz test_ext_partition_3
 
mov eax, [ebx+0x1be+8+16+16]; add relative start
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
test_ext_partition_3:
mov al, [ebx+0x1be+4+16+16+16]; get extended partition type
call scan_extended_types
jnz end_partition_chain; no. end chain
 
mov eax, [ebx+0x1be+8+16+16+16]; get start of extended partition
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
end_partition_chain:
;mov [partition_count],ecx
 
;cmp edx,-1 ; found wanted partition?
;jnz hd_and_partition_ok ; yes. install it
;jmp problem_partition_or_fat
problem_hd:
or [problem_partition], 2
jmp return_from_part_set
 
 
scan_partition_types:
push ecx
mov edi, partition_types
mov ecx, partition_types_end-partition_types
cld
repne scasb ; is partition type ok?
pop ecx
ret
 
scan_extended_types:
push ecx
mov edi, extended_types
mov ecx, extended_types_end-extended_types
cld
repne scasb ; is it extended partition?
pop ecx
ret
 
problem_fat_dec_count: ; bootsector is missing or another problem
; dec [partition_count] ; remove it from partition_count
 
problem_partition_or_fat:
or [problem_partition], 1
 
return_from_part_set:
popad
;mov [fs_type],0
call free_hd_channel
mov [hd1_status], 0 ; free
ret
 
hd_and_partition_ok:
 
;eax = PARTITION_START edx=PARTITION_LENGTH cl=fs_type
mov [fs_type], cl
;mov eax,edx
mov [PARTITION_START], eax
add edx, eax
dec edx
mov [PARTITION_END], edx
 
; mov edx, [PARTITION_END]
; sub edx, eax
; inc edx ; edx = length of partition зачем оно нам??
 
; mov [hd_setup],1
mov ebx, buffer
call hd_read ; read boot sector of partition
cmp [hd_error], 0
jz boot_read_ok
cmp [fs_type], 7
jnz problem_fat_dec_count
; NTFS duplicates bootsector:
; NT4/2k/XP+ saves bootsector copy in the end of disk
; NT 3.51 saves bootsector copy in the middle of disk
and [hd_error], 0
mov eax, [PARTITION_END]
call hd_read
cmp [hd_error], 0
jnz @f
call ntfs_test_bootsec
jnc boot_read_ok
@@:
and [hd_error], 0
mov eax, edx
shr eax, 1
add eax, [PARTITION_START]
call hd_read
cmp [hd_error], 0
jnz problem_fat_dec_count ; no chance...
boot_read_ok:
 
; if we are running on NTFS, check bootsector
 
call ntfs_test_bootsec ; test ntfs
jnc ntfs_setup
 
call ext2_test_superblock ; test ext2fs
jnc ext2_setup
 
mov eax, [PARTITION_START] ;ext2 test changes [buffer]
call hd_read
cmp [hd_error], 0
jnz problem_fat_dec_count
 
push 0
mov eax, [PARTITION_END]
sub eax, [PARTITION_START]
inc eax
push eax
push 0
push [PARTITION_START]
push ebp
push ebp
mov ebp, esp
mov esi, 'old' ; special value: there is no DISK structure
push 1 ; bootsector read successfully
call fat_create_partition
add esp, 4*7
test eax, eax
jz problem_fat_dec_count
mov [fs_dependent_data_start.partition], eax
mov al, [eax+FAT.fs_type]
mov [fs_type], al
 
popad
call free_hd_channel
mov [hd1_status], 0 ; free
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/fs/fs-sp.inc
0,0 → 1,13
dir0:
db 'DISCO DURO '
db 'UNIDAD RAM '
db 'DISQUETE '
db 0
 
dir1:
db 'PRIMERO '
db 'SEGUNDO '
db 'TERCERO '
db 'CUARTO '
db 0
 
/kernel/branches/Kolibri-acpi/gui/char2_et.mt
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/gui/char_et.mt
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/kernel.asm
759,11 → 759,10
; Initialize system timer (IRQ0)
call PIT_init
 
; Register ramdisk file system
mov esi, boot_initramdisk
call boot_log
call ramdisk_init
; CALCULATE FAT CHAIN FOR RAMDISK
 
call calculatefatchain
 
mov esi, boot_initapic
call boot_log
; Try to Initialize APIC
1334,8 → 1333,8
jnz .yes
call stack_handler_has_work?
jnz .yes
call check_fdd_motor_status_has_work?
jnz .yes
; call check_fdd_motor_status_has_work?
; jnz .yes
call check_ATAPI_device_event_has_work?
jnz .yes
call check_lights_state_has_work?
2674,14 → 2673,29
align 4
sys_cachetodiskette:
cmp ebx, 1
jb .no_floppy_save
jne .no_floppy_a_save
mov [flp_number], 1
jmp .save_image_on_floppy
;--------------------------------------
align 4
.no_floppy_a_save:
cmp ebx, 2
ja .no_floppy_save
jne .no_floppy_b_save
mov [flp_number], 2
;--------------------------------------
align 4
.save_image_on_floppy:
call save_image
mov [esp + 32], eax
ret
.no_floppy_save:
mov [esp + 32], dword 0
cmp [FDC_Status], 0
je .yes_floppy_save
;--------------------------------------
align 4
.no_floppy_b_save:
mov [esp + 32], dword 1
;--------------------------------------
align 4
.yes_floppy_save:
ret
;------------------------------------------------------------------------------
uglobal
5252,6 → 5266,19
 
align 4
 
syscall_openramdiskfile: ; OpenRamdiskFile
 
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, 12
call fileread
mov [esp+32], eax
ret
 
align 4
 
syscall_drawrect: ; DrawRect
 
mov edi, edx ; color + gradient
5611,7 → 5638,13
; eax - new Screen_Max_X
; ecx - new BytesPerScanLine
; edx - new Screen_Max_Y
cmp eax, [Screen_Max_X]
jne .set
 
cmp edx, [Screen_Max_Y]
jne .set
ret
.set:
pushfd
cli
 
5750,11 → 5783,12
cli
 
if ~ defined extended_primary_loader
; load kernel.mnt to 0x7000:0
mov ebx, kernel_file_load
pushad
call file_system_lfn
popad
mov eax, kernel_file ; load kernel.mnt to 0x7000:0
movi esi, 12
xor ebx, ebx
or ecx, -1
mov edx, OS_BASE+0x70000
call fileread
 
mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0
mov edi, OS_BASE+0x40000
5768,6 → 5802,8
; cld
; rep movsd
 
call restorefatchain
 
call IRQ_mask_all
 
if 0
/kernel/branches/Kolibri-acpi/kernel32.inc
185,9 → 185,11
 
include "blkdev/disk.inc" ; support for plug-n-play disks
include "blkdev/disk_cache.inc" ; caching for plug-n-play disks
include "fs/fs.inc" ; syscall
include "fs/fat32.inc" ; read / write for fat32 filesystem
include "fs/ntfs.inc" ; read / write for ntfs filesystem
include "fs/fat12.inc" ; read / write for fat12 filesystem
include "blkdev/rd.inc" ; ramdisk read /write
include "fs/fat.inc" ; read / write for fat filesystem
include "fs/ntfs.inc" ; read / write for ntfs filesystem
include "fs/fs_lfn.inc" ; syscall, version 2
include "fs/iso9660.inc" ; read for iso9660 filesystem CD
include "fs/ext2/ext2.asm" ; read / write for ext2 filesystem
/kernel/branches/Kolibri-acpi/data32sp.inc
2,7 → 2,6
boot_picinit: cp850 'Inicializar PIC',0
boot_v86machine: cp850 'Inicializar sistema V86',0
boot_inittimer: cp850 'Inicializar reloj del sistema (IRQ0)',0
boot_initramdisk cp850 'Initialize ramdisk',0
boot_initapic: cp850 'Prueba inicializar APIC',0
boot_enableirq: cp850 'Habilitar interrupciones 2, 13',0
boot_disabling_ide:cp850 'Habiliar interrupciones en controladores IDE',0
/kernel/branches/Kolibri-acpi/memmap.inc
198,7 → 198,8
; 0x800A0000 -> AFFFF screen access area
; 0x800B0000 -> FFFFF bios rest in peace -area (320k) ?
; 0x80100000 -> 27FFFF diskette image (1m5)
; 0x80280000 -> 283FFF free (16k)
; 0x80280000 -> 281FFF ramdisk fat (8k)
; 0x80282000 -> 283FFF floppy fat (8k)
;
; 0x80284000 -> 28BFFF HDD DMA AREA (32k)
; 0x8028C000 -> 297FFF free (48k)
/kernel/branches/Kolibri-acpi/skin/default.asm
0,0 → 1,38
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
include 'me_skin.inc'
 
SKIN_PARAMS \
height = bmp_base.height,\ ; skin height
margins = [5:1:43:1],\ ; margins [left:top:right:bottom]
colors active = [binner=0x00081d:\ ; border inner color
bouter=0x00081d:\ ; border outer color
bframe=0x0054e7],\ ; border frame color
colors inactive = [binner=0x00081d:\ ; border inner color
bouter=0x00081d:\ ; border outer color
bframe=0x1a8acc],\ ; border frame color
dtp = 'myblue.dtp' ; dtp colors
 
SKIN_BUTTONS \
close = [-21:3][16:16],\ ; buttons coordinates
minimize = [-39:3][16:16] ; [left:top][width:height]
 
SKIN_BITMAPS \
left active = bmp_left,\ ; skin bitmaps pointers
left inactive = bmp_left1,\
oper active = bmp_oper,\
oper inactive = bmp_oper1,\
base active = bmp_base,\
base inactive = bmp_base1
 
BITMAP bmp_left ,'left.bmp' ; skin bitmaps
BITMAP bmp_oper ,'oper.bmp'
BITMAP bmp_base ,'base.bmp'
BITMAP bmp_left1,'left_1.bmp'
BITMAP bmp_oper1,'oper_1.bmp'
BITMAP bmp_base1,'base_1.bmp'
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/me_skin.inc
0,0 → 1,242
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;============================================================================
; This file should be used to generate skins of new standard
;============================================================================
; skin file structure:
;----------------------------------------------------------------------------
; header:
; dd 'SKIN'
; dd = version (1 for now)
; dd @ params
; dd @ buttons
; dd @ bitmaps
; ...
;----------------------------------------------------------------------------
; NOTE: order of sections listed below is insignificant
; since they're identified by pointer in above header
;----------------------------------------------------------------------------
; ...
; params:
; dd = skin height
; dw = right margin
; dw = left margin
; dw = bottom margin
; dw = top margin
; dd = inner line color
; dd = outer line color
; dd = frame color
; dd = dtp file size
; ?? = dtp file itself
; ...
;----------------------------------------------------------------------------
; ...
; buttons:
; dd = button type (1 = close, 2 = minimize)
; dw = left button coord (could be negative)
; dw = top button coord (could be negative)
; dw = button width
; dw = button height
; ... etc for all buttons
; dd = 0 (end of buttons list)
; ...
;----------------------------------------------------------------------------
; ...
; bitmaps:
; dw = bitmap kind (1 = left, 2 = oper, 3 = base)
; dw = bitmap type (1 = active, 0 = inactive)
; dd @ bitmap
; ... etc for all bitmaps
; dd 0 (end of bitmaps list)
; ...
;----------------------------------------------------------------------------
; ...
; bitmap:
; dd = bitmap width
; dd = bitmap height
; ?? = raw bitmap data
; ... etc for all bitmaps
; ...
;============================================================================
 
dd 'SKIN',1,__params__,__buttons__,__bitmaps__
 
struc BITMAPFILEHEADER {
.bfType dw ? ; WORD
.bfSize dd ? ; DWORD
.bfReserved1 dw ? ; WORD
.bfReserved2 dw ? ; WORD
.bfOffBits dd ? ; DWORD
}
 
struc BITMAPINFOHEADER {
.biSize dd ? ; DWORD
.biWidth dd ? ; LONG
.biHeight dd ? ; LONG
.biPlanes dw ? ; WORD
.biBitCount dw ? ; WORD
.biCompression dd ? ; DWORD
.biSizeImage dd ? ; DWORD
.biXPelsPerMeter dd ? ; LONG
.biYPelsPerMeter dd ? ; LONG
.biClrUsed dd ? ; DWORD
.biClrImportant dd ? ; DWORD
}
 
struc _bmp {
.h BITMAPFILEHEADER
.i BITMAPINFOHEADER
}
virtual at 0
_bmp _bmp
end virtual
 
macro BITMAP _name*,_fname*
{
local w,h,a,r,g,b
virtual at 0
file _fname
load w dword from _bmp.i.biWidth
load h dword from _bmp.i.biHeight
end virtual
align 4
label _name
.width = w
.height = h
dd w,h
a=54+(w*3+(w mod 4))*(h-1)
size = $
repeat h
repeat w
virtual at 0
file _fname
load r from a+0
load g from a+1
load b from a+2
end virtual
db r,g,b
a=a+3
end repeat
a=a-w*3*2-(w mod 4)
end repeat
}
 
macro define_colors name,[col,val]
{
common
local a,b,c
forward
match =binner,col \{ a = val \}
match =bouter,col \{ b = val \}
match =bframe,col \{ c = val \}
common
name equ a,b,c
}
 
macro SKIN_PARAMS [a]
{
common
local _height,_margins,_colors,_colors_1,_dtp,_dtp_sz
__params__:
forward
match qq == ww,a
\{
match =height,qq \\{ _height = ww \\}
match =margins,qq \\{
match [q1:q2:q3:q4],ww
\\\{
_margins equ q3,q1,q4,q2
\\\}
\\}
match =colors =active,qq
\\{
match [q10==q11:q20==q21:q30==q31],ww
\\\{
define_colors _colors,q10,q11,q20,q21,q30,q31
\\\}
\\}
match =colors =inactive,qq
\\{
match [q10==q11:q20==q21:q30==q31],ww
\\\{
define_colors _colors_1,q10,q11,q20,q21,q30,q31
\\\}
\\}
match =dtp,qq \\{ _dtp equ ww \\}
\}
common
dd _height
dw _margins
dd _colors,_colors_1
virtual at 0
file _dtp
_dtp_sz = $
end virtual
dd _dtp_sz
file _dtp
}
 
macro SKIN_BUTTONS [a]
{
common
local btn
__buttons__:
forward
match qq == ww,a
\{
btn = 0
match =close,qq \\{ btn = 1 \\}
match =minimize,qq \\{ btn = 2 \\}
match [q1:q2][q3:q4],ww
\\{
if btn <> 0
dd btn
dw q1,q2,q3,q4
end if
\\}
\}
common
dd 0
}
 
macro SKIN_BITMAPS [a]
{
common
local bmp
__bitmaps__:
forward
match qq == ww,a
\{
bmp=-1
match qqq =active,qq \\{ bmp = 1 \\}
match qqq =inactive,qq \\{ bmp = 0 \\}
match =left qqq,qq
\\{
if bmp >= 0
dw 1,bmp
dd ww
end if
\\}
match =oper qqq,qq
\\{
if bmp >= 0
dw 2,bmp
dd ww
end if
\\}
match =base qqq,qq
\\{
if bmp >= 0
dw 3,bmp
dd ww
end if
\\}
\}
common
dd 0
}
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/base.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/base_1.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/left.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/left_1.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/myblue.dtp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/oper.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin/oper_1.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/Kolibri-acpi/skin
Property changes:
Added: svn:ignore
+*.mnt
+lang.inc
+*.bat
+out.txt
+scin*
+*.obj