From 6e1bd6d91ddfc64336910d21d5fb86feaca6b8c5 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Wed, 17 Feb 2016 02:56:18 +0000 Subject: [PATCH] kos-acpi: kernel restart reboot and shutdown git-svn-id: svn://kolibrios.org@6240 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../branches/Kolibri-acpi/boot/shutdown.inc | 50 +- kernel/branches/Kolibri-acpi/const.inc | 4 + kernel/branches/Kolibri-acpi/core/sync.inc | 17 +- kernel/branches/Kolibri-acpi/core/taskman.inc | 13 +- kernel/branches/Kolibri-acpi/data32.inc | 7 +- .../branches/Kolibri-acpi/docs/sysfuncr.txt | 38 +- .../branches/Kolibri-acpi/docs/sysfuncs.txt | 67 +- kernel/branches/Kolibri-acpi/fs/ntfs.inc | 1599 ++++++++++++----- kernel/branches/Kolibri-acpi/init.inc | 27 +- kernel/branches/Kolibri-acpi/kernel.asm | 305 ++-- kernel/branches/Kolibri-acpi/network/IPv4.inc | 13 +- .../branches/Kolibri-acpi/video/cursors.inc | 6 +- 12 files changed, 1417 insertions(+), 729 deletions(-) diff --git a/kernel/branches/Kolibri-acpi/boot/shutdown.inc b/kernel/branches/Kolibri-acpi/boot/shutdown.inc index df17814c44..cbd5de76a4 100644 --- a/kernel/branches/Kolibri-acpi/boot/shutdown.inc +++ b/kernel/branches/Kolibri-acpi/boot/shutdown.inc @@ -15,7 +15,14 @@ $Revision$ use32 become_real: + xor ebx, ebx + xor edx, edx + xor ecx, ecx + xor esi, esi + xor edi, edi + xor ebp, ebp cli + ltr bx lgdt [realmode_gdt-OS_BASE] jmp 8:@f use16 @@ -34,10 +41,11 @@ use16 pr_mode_exit: ; setup stack - mov ax, 0x3000 + mov ax, (TMP_STACK_TOP and 0xF0000) shr 4 mov ss, ax - mov esp, 0x0EC00 -; setup ds + mov esp, TMP_STACK_TOP and 0xFFFF + +;setup ds push cs pop ds @@ -173,31 +181,41 @@ restart_kernel: mov ax, 0x0003 ; set text mode for screen int 0x10 - jmp 0x4000:0000 + jmp 0x5000:0000 -restart_kernel_4000: +restart_kernel_5001: cli push ds pop es - mov cx, 0x8000 - push cx - push 0x7100 - pop ds xor si, si xor di, di - rep movsw - pop cx - mov ds, cx + + push 0x7100 + pop ds + mov cx, 0x4000 + rep movsd + + push 0x8100 + pop ds push 0x2000 pop es - rep movsw - push 0x9000 + mov cx, 0x4000 + rep movsd + + push 0x9100 pop ds push 0x3000 pop es - mov cx, 0xE000/2 - rep movsw + mov cx, 0x4000 + rep movsd +xchg bx, bx + push 0xA100 + pop ds + push 0x4000 + pop es + mov cx, 0x800 + rep movsd wbinvd ; write and invalidate cache diff --git a/kernel/branches/Kolibri-acpi/const.inc b/kernel/branches/Kolibri-acpi/const.inc index 368e4e6547..f9b562f7d8 100644 --- a/kernel/branches/Kolibri-acpi/const.inc +++ b/kernel/branches/Kolibri-acpi/const.inc @@ -358,6 +358,10 @@ STDIN_FILENO equ 0 STDOUT_FILENO equ 1 STDERR_FILENO equ 2 +SYSTEM_SHUTDOWN equ 2 +SYSTEM_REBOOT equ 3 +SYSTEM_RESTART equ 4 + struct SYSCALL_STACK _eip dd ? _edi dd ? ; +4 diff --git a/kernel/branches/Kolibri-acpi/core/sync.inc b/kernel/branches/Kolibri-acpi/core/sync.inc index d52cdf490b..b9067f9f1e 100644 --- a/kernel/branches/Kolibri-acpi/core/sync.inc +++ b/kernel/branches/Kolibri-acpi/core/sync.inc @@ -132,10 +132,10 @@ align 4 jnz .futex_wait_timeout mov ecx, [ebp+FUTEX.pointer] mov eax, edx - lock cmpxchg [ecx], edx ;wait until old_value == new_value - jz .wait_slow + lock cmpxchg [ecx], edx + je .wait_slow - mov [esp+SYSCALL_STACK._eax], 0 + mov [esp+SYSCALL_STACK._eax], -2 ret .wait_slow: @@ -148,13 +148,13 @@ align 4 lea esi, [ebp+FUTEX.wait_list] list_add_tail esp, esi ;esp= new waiter, esi= list head - + mov eax, edx .again: mov [ebx+TASKDATA.state], 1 call change_task lock cmpxchg [ecx], edx - jz .again + je .again list_del esp add esp, sizeof.MUTEX_WAITER @@ -174,9 +174,9 @@ align 4 mov ecx, [ebp+FUTEX.pointer] mov eax, edx lock cmpxchg [ecx], edx ;wait until old_value == new_value - jz .wait_slow_timeout + je .wait_slow_timeout - mov [esp+SYSCALL_STACK._eax], 0 + mov [esp+SYSCALL_STACK._eax], -2 ret align 4 @@ -210,6 +210,7 @@ align 4 test eax, eax jz .timeout + mov eax, edx lock cmpxchg [ecx], edx jz .again_timeout @@: @@ -231,7 +232,7 @@ align 4 align 4 ;ecx futex handle -;edx numder of threads +;edx number of threads ;edi current process ;ebp futex object .futex_wake: diff --git a/kernel/branches/Kolibri-acpi/core/taskman.inc b/kernel/branches/Kolibri-acpi/core/taskman.inc index f8b5f33c32..09f88788d2 100644 --- a/kernel/branches/Kolibri-acpi/core/taskman.inc +++ b/kernel/branches/Kolibri-acpi/core/taskman.inc @@ -940,12 +940,6 @@ proc new_sys_threads mov ecx, 11 rep movsb ;copy process name - mov eax, [ebx+APPDATA.process] - mov [edx+APPDATA.process], eax - - lea ebx, [edx+APPDATA.list] - lea ecx, [eax+PROC.thr_list] - list_add_tail ebx, ecx ;add thread to process child's list mov eax, [ebx+APPDATA.tls_base] test eax, eax @@ -959,6 +953,13 @@ proc new_sys_threads @@: mov [edx+APPDATA.tls_base], eax + mov eax, [ebx+APPDATA.process] + mov [edx+APPDATA.process], eax + + lea ebx, [edx+APPDATA.list] + lea ecx, [eax+PROC.thr_list] + list_add_tail ebx, ecx ;add thread to process child's list + lea eax, [app_cmdline] stdcall set_app_params , [slot], eax, dword 0, \ dword 0, [flags] diff --git a/kernel/branches/Kolibri-acpi/data32.inc b/kernel/branches/Kolibri-acpi/data32.inc index a2f8b3aca5..7017547411 100644 --- a/kernel/branches/Kolibri-acpi/data32.inc +++ b/kernel/branches/Kolibri-acpi/data32.inc @@ -173,11 +173,12 @@ end if vmode db '/sys/drivers/VMODE.MDR',0 ;vrr_m db 'VRR_M',0 kernel_file_load: -; load kernel.mnt to 0x7000:0 + +; load kernel.mnt to _CLEAN_ZONE dd 0 ; subfunction dq 0 ; offset in file - dd 0x30000 ; number of bytes to read - dd OS_BASE + 0x71000 ; buffer for data + dd 0x31000 ; number of bytes to read + dd _CLEAN_ZONE ; buffer for data db '/RD/1/KERNEL.MNT',0 dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0 diff --git a/kernel/branches/Kolibri-acpi/docs/sysfuncr.txt b/kernel/branches/Kolibri-acpi/docs/sysfuncr.txt index d30ec9fd65..c1b0bf03d7 100644 --- a/kernel/branches/Kolibri-acpi/docs/sysfuncr.txt +++ b/kernel/branches/Kolibri-acpi/docs/sysfuncr.txt @@ -25,20 +25,18 @@ * ecx = [координата по оси y]*65536 + [размер по оси y] * edx = 0xXYRRGGBB, где: * Y = стиль окна: - * Y=0 - тип I - окно фиксированных размеров * Y=1 - только определить область окна, ничего не рисовать - * Y=2 - тип II - окно изменяемых размеров * Y=3 - окно со скином * Y=4 - окно со скином фиксированных размеров + * Y=0,2 эти стили являются устаревшими и не должны более использоваться, + они оставлены для совместимости со старыми приложениями * остальные возможные значения (от 5 до 15) зарезервированы, вызов функции с такими Y игнорируется * RR, GG, BB = соответственно красная, зеленая, синяя составляющие цвета рабочей области окна (игнорируется для стиля Y=1) * X = DCBA (биты) - * A = 1 - у окна есть заголовок; для стилей Y=3,4 адрес строки - заголовка задаётся в edi, для прочих стилей - используется подфункция 1 функции 71 + * A = 1 - у окна есть заголовок * B = 1 - координаты всех графических примитивов задаются относительно клиентской области окна * C = 1 - не закрашивать рабочую область при отрисовке окна @@ -52,7 +50,7 @@ X=8 - обычный градиент, для окон типа II X=4 - негативный градиент * прочие значения X и Y зарезервированы - * edi = 0x00RRGGBB - цвет рамки + * edi = адрес строки заголовка для стилей Y=3,4 (также см. функцию 71.1) Возвращаемое значение: * функция не возвращает значения Замечания: @@ -82,35 +80,9 @@ * Размеры окна понимаются в смысле координат правого нижнего угла. Это же относится и ко всем остальным функциям. Это означает, что реальные размеры на 1 пиксель больше. - * Вид окна типа I: - * рисуется внешняя рамка цвета, указанного в edi, - шириной 1 пиксель - * рисуется заголовок - прямоугольник с левым верхним углом (1,1) - и правым нижним (xsize-1,min(20,ysize-1)) цвета, указанного в esi - (с учетом градиента) - * если ysize>21, то закрашивается рабочая область окна - - прямоугольник с левым верхним углом (1,21) и правым нижним - (xsize-1,ysize-1) (размерами (xsize-1)*(ysize-21)) - цветом, - указанным в edx (с учетом градиента) - * если A=1 и строка заголовка установлена подфункцией 1 - функции 71, то она выводится в соответствующем месте заголовка * Вид окна стиля Y=1: * полностью определяется приложением - * Вид окна типа II: - * рисуется внешняя рамка шириной 1 пиксель "затенённого" цвета - edi (все составляющие цвета уменьшаются в два раза) - * рисуется промежуточная рамка шириной 3 пикселя цвета edi - * рисуется внутренняя рамка шириной 1 пиксель - "затенённого" цвета edi - * рисуется заголовок - прямоугольник с левым верхним углом (4,4) - и правым нижним (xsize-4,min(20,ysize)) цвета, указанного в esi - (с учетом градиента) - * если ysize>=26, то закрашивается рабочая область окна - - прямоугольник с левым верхним углом (5,20) и правым нижним - (xsize-5,ysize-5) - цветом, указанным в edx (с учетом градиента) - * если A=1 и строка заголовка установлена подфункцией 1 - функции 71, то она выводится в соответствующем месте заголовка - * Вид окна со скином: + * Вид окна со скином Y=3,4: * рисуется внешняя рамка шириной 1 пиксель цвета 'outer' из скина * рисуется промежуточная рамка шириной 3 пикселя diff --git a/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt b/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt index 767642bd62..fbec0aa0de 100644 --- a/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt +++ b/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt @@ -25,19 +25,17 @@ Parameters: * ecx = [coordinate on axis y]*65536 + [size on axis y] * edx = 0xXYRRGGBB, where: * Y = style of the window: - * Y=0 - type I - fixed-size window * Y=1 - only define window area, draw nothing - * Y=2 - type II - variable-size window * Y=3 - skinned window * Y=4 - skinned fixed-size window - * other possible values (from 5 up to 15) are reserved, + * Y=0,2 window types are outdated and should not be used anymore, + they are retained for compatibility with old programs. + * other possible values (from 5 to 15) are reserved, function call with such Y is ignored * RR, GG, BB = accordingly red, green, blue components of a color of the working area of the window (are ignored for style Y=1) * X = DCBA (bits) - * A = 1 - window has caption; for styles Y=3,4 caption string - must be passed in edi, for other styles use - subfunction 1 of function 71 + * A = 1 - window has caption * B = 1 - coordinates of all graphics primitives are relative to window client area * C = 1 - don't fill working area on window draw @@ -47,11 +45,8 @@ Parameters: * esi = 0xXYRRGGBB - color of the header * RR, GG, BB define color * Y=0 - usual window, Y=1 - unmovable window (works for all window styles) - * X defines a gradient of header: X=0 - no gradient, - X=8 - usual gradient, - for windows of a type II X=4 - negative gradient - * other values of X and Y are reserved - * edi = 0x00RRGGBB - color of the frame + * X not used, other values of Y are reserved + * edi = caption string for styles Y=3,4 (also can be set by func 71.1) Returned value: * function does not return value Remarks: @@ -79,34 +74,9 @@ Remarks: * The sizes of the window are understood in sence of coordinates of the right lower corner. This concerns all other functions too. It means, that the real sizes are on 1 pixel more. - * The window of type I looks as follows: - * draw external frame of color indicated in edi, 1 pixel in width - * draw header - rectangle with the left upper corner (1,1) and - right lower (xsize-1,min(20,ysize-1)) color indicated in esi - (taking a gradient into account) - * if ysize>21, fill the working area of the window - - rectangle with the left upper corner (1,21) and right lower - (xsize-1,ysize-1) (sizes (xsize-1)*(ysize-21)) with color - indicated in edx (taking a gradient into account) - * if A=1 and caption has been already set by subfunction 1 - of function 71, it is drawn in the corresponding place of header * The window of style Y=1 looks as follows: * completely defined by the application - * The window of type II looks as follows: - * draw external frame of width 1 pixel with the "shaded" color - edi (all components of the color decrease twice) - * draw intermediate frame of width 3 pixels with color edi - * draw internal frame of width 1 pixel with the "shaded" color edi - * draw header - rectangle with the left upper corner (4,4) - and right lower (xsize-4,min(20,ysize)) color, indicated in esi - (taking a gradient into account) - * if ysize>=26, fill the working area of the window - - rectangle with the left upper corner (5,20) and right lower - (xsize-5,ysize-5) with color indicated in edx - (taking a gradient into account) - * if A=1 and caption has been already set by subfunction 1 - of function 71, it is drawn in the corresponding place of header - * The skinned window looks as follows: + * The skinned window Y=3,4 looks as follows: * draw external frame of width 1 pixel with color 'outer' from the skin * draw intermediate frame of width 3 pixel @@ -4794,14 +4764,31 @@ Parameters: * edx = control value * esi = timeout in system ticks or 0 for infinity Returned value: - * eax = 0 - successfull, -1 on timeout - + * eax = 0 - successfull + -1 - timeout + -2 - futex dword does not have the same value as edx Remarks: - * This operation tests that the value at the futex dword still + * This functionn tests that the value at the futex dword still contains the expected control value, and if so, then sleeps waiting for a wake operation on the futex. * The futex handle must have been created by subfunction 0 +====================================================================== +=============== Function 77, Subfunction 3, Futex wake =============== +====================================================================== +Parameters: + * eax = 77 - function number + * ebx = 3 - subfunction number + * ecx = futex handle + * edx = number of waiters to wake +Returned value: + * eax = number of waiters that were woken up + +Remarks: + * This function wakes at most edx of the waiters that are + waiting (e.g., inside futex wait) on the futex dword + * The futex handle must have been created by subfunction 0 + ====================================================================== =============== Function -1 - terminate thread/process =============== ====================================================================== diff --git a/kernel/branches/Kolibri-acpi/fs/ntfs.inc b/kernel/branches/Kolibri-acpi/fs/ntfs.inc index 6d9a6ab0a4..d8f8986b51 100644 --- a/kernel/branches/Kolibri-acpi/fs/ntfs.inc +++ b/kernel/branches/Kolibri-acpi/fs/ntfs.inc @@ -48,9 +48,12 @@ nameLength = 9 nameOffset = 10 attributeFlags = 12 attributeID = 14 -sizeWithoutHeader = 16 + ; resident attribute header +sizeWithoutHeader = 10h +; attributeOffset = 14h indexedFlag = 16h ; non resident attribute header +firstVCN = 10h lastVCN = 18h dataRunsOffset = 20h attributeAllocatedSize = 28h @@ -439,6 +442,9 @@ ntfs_create_partition: mov eax, [ebp+NTFS.ntfs_cur_read] cmp eax, 4 jc .failFreeBitmapMFT + mov ecx, [ebp+NTFS.ntfs_attr_offs] + cmp byte [ecx+nonResidentFlag], 1 + jnz .failFreeBitmapMFT mov [ebp+NTFS.mftBitmapSize], eax mov eax, [ebp+NTFS.ntfsLastRead] mov [ebp+NTFS.mftBitmapLocation], eax @@ -657,18 +663,19 @@ ntfs_read_attr: jc .errret ; 2. Find required attribute. mov eax, [ebp+NTFS.frs_buffer] -; a) For auxiliary records, read base record -; N.B. If base record is present, -; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero +; a) For auxiliary records, read base record. +; If base record is present, base iRecord may be 0 (for $Mft), +; but SequenceNumber is nonzero. cmp dword [eax+24h], 0 jz @f mov eax, [eax+20h] -; test eax, eax -; jz @f .beginfindattr: mov [ebp+NTFS.ntfs_attr_iRecord], eax call ntfs_read_file_record jc .errret + jmp @f +.newAttribute: + pushad @@: ; b) Scan for required attribute and for $ATTR_LIST mov eax, [ebp+NTFS.frs_buffer] @@ -1070,7 +1077,7 @@ ntfs_read_attr: ntfs_read_file_record: ; in: eax = iRecord -; out: [ebp+NTFS.frs_buffer] = record data +; out: [ebp+NTFS.frs_buffer] -> file record ; CF=1 -> failed, eax = disk error code, eax=0 -> something with FS ; Read attr $DATA of $Mft, starting from eax*[ebp+NTFS.frs_size] push ecx edx @@ -1135,6 +1142,9 @@ ntfs_read_file_record: ntfs_restore_usa_frs: mov eax, [ebp+NTFS.frs_size] ntfs_restore_usa: +; in: +; ebx -> record +; eax = size in bytes pushad shr eax, 9 mov ecx, eax @@ -1163,13 +1173,13 @@ ntfs_restore_usa: ntfs_decode_mcb_entry: ; in: -; esi -> mcb entry +; esi -> MCB entry ; esp -> buffer (16 bytes) ; out: -; esi -> next mcb entry +; esi -> next MCB entry ; esp -> data run size ; esp+8 -> cluster (delta) -; CF=0 -> mcb end +; CF=0 -> MCB end push eax ecx edi lea edi, [esp+16] xor eax, eax @@ -1999,59 +2009,79 @@ ntfs_CreateFile: @@: ; 1. Search file call ntfs_lock stdcall ntfs_find_lfn, [esp+4] - jnc .found - cmp [ebp+NTFS.ntfsFragmentCount], 1 - jnz ntfsUnsupported ; record fragmented - test eax, eax - jz ntfsFail - jmp .notFound - -.found: ; rewrite + jc .notFound +; found, rewrite cmp [ebp+NTFS.ntfs_cur_iRecord], 16 jc ntfsDenied cmp [ebp+NTFS.ntfsFolder], 1 - jz ntfsDenied + jz .folder + cmp [ebp+NTFS.ntfsFragmentCount], 1 + jnz ntfsUnsupported ; record fragmented +; edit directory node + mov edi, [ebp+NTFS.cur_index_buf] + cmp dword [edi], 'INDX' + jz @f + mov esi, [ebp+NTFS.frs_buffer] + mov ecx, [esi+recordRealSize] + shr ecx, 2 + rep movsd + mov esi, [ebp+NTFS.ntfs_attr_offs] + mov cl, [esi+attributeOffset] + sub esi, [ebp+NTFS.frs_buffer] + add eax, ecx + add eax, esi +@@: + mov edx, [ebx+12] + mov [eax+fileRealSize], edx + mov dword [eax+fileRealSize+4], 0 + mov eax, [ebp+NTFS.ntfsLastRead] + mov [ebp+NTFS.nodeLastRead], eax mov [ebp+NTFS.ntfs_cur_attr], 0x80 mov [ebp+NTFS.ntfs_cur_offs], 0 mov [ebp+NTFS.ntfs_cur_size], 0 call ntfs_read_attr - jc ntfsDenied - mov eax, [ebp+NTFS.frs_buffer] - cmp word [eax+baseRecordReuse], 0 + jc ntfsFail + mov ecx, [ebp+NTFS.frs_buffer] + mov eax, edx + xor edx, edx + cmp word [ecx+baseRecordReuse], 0 jnz ntfsUnsupported ; auxiliary record - cmp byte [eax+hardLinkCounter], 1 - jnz ntfsUnsupported ; file copying required mov ecx, [ebp+NTFS.ntfs_attr_offs] - cmp byte [ecx+nonResidentFlag], 1 - jnz ntfsUnsupported ; resident $DATA - mov eax, [ebx+4] - mov edx, [ebx+8] - add eax, [ebx+12] - adc edx, 0 - cmp edx, [ecx+attributeRealSize+4] + cmp word [ecx+attributeFlags], 0 jnz ntfsUnsupported + push ebx + cmp byte [ecx+nonResidentFlag], 0 + jz @f + cmp [ecx+attributeRealSize+4], edx + jnz @f cmp [ecx+attributeRealSize], eax - jnz ntfsUnsupported - jmp ntfs_WriteFile.write + jz ntfs_WriteFile.writeNode +@@: + jmp ntfs_WriteFile.resizeAttribute -.notFound: ; create; check path folders - cmp dword [esp+4], 0 - jnz ntfsNotFound - cmp byte [esi], 0 - jz ntfsNotFound +.folder: + bt dword [eax+fileFlags], 28 + jnc ntfsDenied + push 0 + jmp ntfsOut + +.notFound: ; create + test eax, eax + jz ntfsFail + cmp [ebp+NTFS.ntfsFragmentCount], 1 + jnz ntfsUnsupported ; record fragmented ; 2. Prepare directory record mov ecx, esi @@: ; count characters inc ecx cmp byte [ecx], '/' - jz ntfsNotFound + jz ntfsNotFound ; path folder not found cmp byte [ecx], 0 jnz @b sub ecx, esi push ecx - lea ecx, [ecx*2+52h] ; precalculate index length - add ecx, 7 ; align 8 - and ecx, not 7 + lea ecx, [ecx*2+52h+7] ; precalculate index length + and ecx, not 7 ; align 8 mov edi, [ebp+NTFS.cur_index_buf] push esi push ecx @@ -2111,11 +2141,12 @@ ntfs_CreateFile: rep stosd cld add edi, 4 - pop eax + pop ecx pop esi - mov [edi+indexAllocatedSize], ax ; fill index with data + mov [edi+indexAllocatedSize], cx ; fill index with data mov eax, [esp] - lea eax, [eax*2+42h] + shl eax, 1 + add eax, 42h mov [edi+indexRawSize], ax mov eax, [ebp+NTFS.ntfs_attr_iRecord] mov [edi+directoryRecordReference], eax @@ -2123,8 +2154,16 @@ ntfs_CreateFile: mov eax, [eax+reuseCounter] mov [edi+directoryReferenceReuse], ax mov eax, [ebx+12] + add ecx, 30h+48h+8+18h+8 + add ecx, eax mov [ebp+NTFS.fileRealSize], eax mov [edi+fileRealSize], eax + cmp [ebp+NTFS.frs_size], ecx + jc @f + mov eax, [ebx+16] + mov [ebp+NTFS.fileDataStart], eax + xor eax, eax +@@: mov ecx, [ebp+NTFS.sectors_per_cluster] shl ecx, 9 add eax, ecx @@ -2149,23 +2188,767 @@ ntfs_CreateFile: cmp [ebp+NTFS.ntfsFolder], 0 jz @f mov edi, [ebp+NTFS.indexOffset] - mov byte [edi+fileFlags+3], 16 + bts dword [edi+fileFlags], 28 jmp .mftBitmap @@: ; 3. File data - cmp [ebp+NTFS.fileRealSize], 0 + cmp [ebp+NTFS.fileDataSize], 0 jz .mftBitmap -; One piece free space bitmap search engine - mov edi, [ebp+NTFS.BitmapBuffer] - add edi, [ebp+NTFS.BitmapStart] + mov edi, [ebp+NTFS.BitmapStart] + call ntfsSpaceAlloc + jc ntfsDiskFull + mov [ebp+NTFS.fileDataStart], eax + mul [ebp+NTFS.sectors_per_cluster] + mov ecx, [ebp+NTFS.fileRealSize] + add ecx, 511 + shr ecx, 9 + mov ebx, [ebx+16] + call fs_write64_app + test eax, eax + jnz ntfsDevice + ; 4. MFT record +.mftBitmap: ; search for free record + mov edi, [ebp+NTFS.mftBitmapBuffer] + mov ecx, [ebp+NTFS.mftBitmapSize] + mov al, -1 + add edi, 3 + sub ecx, 3 + repz scasb + dec edi + movzx eax, byte [edi] + not al + bsf ecx, eax + jz .extendBitmapMFT ; no free records + bts [edi], ecx +; get record location + sub edi, [ebp+NTFS.mftBitmapBuffer] + shl edi, 3 + add edi, ecx + mov [ebp+NTFS.newMftRecord], edi + mov eax, [ebp+NTFS.frs_size] + shr eax, 9 + mul edi + mov [ebp+NTFS.ntfs_cur_iRecord], 0 + mov [ebp+NTFS.ntfs_cur_attr], 0x80 + mov [ebp+NTFS.ntfs_cur_offs], eax + mov [ebp+NTFS.ntfs_cur_size], 1 + mov eax, [ebp+NTFS.frs_buffer] + mov [ebp+NTFS.ntfs_cur_buf], eax + call ntfs_read_attr + cmp [ebp+NTFS.ntfs_cur_read], 0 + jz .extendMFT + jmp .mftRecord + +.extendBitmapMFT: + mov eax, [ebp+NTFS.sectors_per_cluster] + shl eax, 9 + cmp [ebp+NTFS.mftBitmapSize], eax + jnc ntfsUnsupported + mov [ebp+NTFS.ntfs_cur_iRecord], 0 + mov [ebp+NTFS.ntfs_cur_attr], 0xB0 + mov [ebp+NTFS.ntfs_cur_offs], 0 + mov [ebp+NTFS.ntfs_cur_size], 0 + call ntfs_read_attr + jc ntfsFail + mov eax, [ebp+NTFS.mft_cluster] + mul [ebp+NTFS.sectors_per_cluster] + cmp eax, [ebp+NTFS.ntfsLastRead] + jnz ntfsUnsupported ; auxiliary record + mov edi, [ebp+NTFS.mftBitmapBuffer] + mov ecx, [ebp+NTFS.mftBitmapSize] + add edi, ecx + mov eax, ecx + mov edx, [ebp+NTFS.ntfs_attr_offs] + add ecx, 8 + mov [edx+attributeRealSize], ecx + mov [edx+initialDataSize], ecx + shl eax, 3 + mov [ebp+NTFS.newMftRecord], eax + mov dword [edi], 1 + mov dword [edi+4], 0 + mov [ebp+NTFS.ntfs_cur_attr], 0x80 + call ntfs_read_attr.newAttribute + jc ntfsFail + mov [ebp+NTFS.mftBitmapSize], ecx +.extendMFT: + mov eax, [ebp+NTFS.mft_cluster] + mul [ebp+NTFS.sectors_per_cluster] + cmp eax, [ebp+NTFS.ntfsLastRead] + jnz ntfsUnsupported ; auxiliary record + mov ecx, [ebp+NTFS.ntfs_attr_offs] + mov eax, [ecx+attributeRealSize] + mov edx, [ecx+attributeRealSize+4] + xor ax, ax + add eax, 10000h + adc edx, 0 + push [ebp+NTFS.fileDataStart] + push [ebp+NTFS.fileDataSize] + call resizeAttribute + jc ntfsErrorPop2 + mov eax, [ebp+NTFS.frs_buffer] + mov [ebp+NTFS.ntfs_cur_buf], eax + call writeRecord ; $MFT + mov eax, [ebp+NTFS.mftmirr_cluster] + mul [ebp+NTFS.sectors_per_cluster] + mov ebx, [ebp+NTFS.frs_buffer] + movzx ecx, word [ebx+updateSequenceSize] + dec ecx + call fs_write64_sys ; $MFTMirr + call ntfsSpaceClean + pop [ebp+NTFS.fileDataSize] + pop [ebp+NTFS.fileDataStart] +.mftRecord: + mov ecx, [ebp+NTFS.frs_size] + shr ecx, 2 + mov edi, [ebp+NTFS.frs_buffer] + xor eax, eax + rep stosd + mov edi, [ebp+NTFS.frs_buffer] +; record header + mov eax, [ebp+NTFS.frs_size] + mov [edi+recordAllocatedSize], eax + shr eax, 9 + inc eax + mov [edi+updateSequenceSize], al + mov dword[edi], 'FILE' + mov byte [edi+updateSequenceOffset], 2ah + mov byte [edi+hardLinkCounter], 1 + mov byte [edi+attributeOffset], 30h + mov byte [edi+newAttributeID], 3 + rdtsc + mov [edi+2ah], ax + add edi, 30h +; $StandardInformation + mov byte [edi+attributeType], 10h + mov byte [edi+sizeWithHeader], 48h + mov byte [edi+sizeWithoutHeader], 30h + mov byte [edi+attributeOffset], 18h + add edi, 48h +; $FileName + mov esi, [ebp+NTFS.indexOffset] + mov byte [edi+attributeType], 30h + mov byte [edi+attributeID], 1 + mov byte [edi+attributeOffset], 18h + mov byte [edi+indexedFlag], 1 + mov cx, [esi+indexRawSize] + mov [edi+sizeWithoutHeader], ecx + mov cx, [esi+indexAllocatedSize] + add ecx, 8 + mov [edi+sizeWithHeader], ecx + add edi, 18h + add esi, 16 + sub ecx, 18h + shr ecx, 2 + rep movsd + mov byte [edi+sizeWithHeader], 50h + mov byte [edi+attributeID], 2 + cmp [ebp+NTFS.ntfsFolder], 1 + jz .indexRoot +; $Data + mov byte [edi+attributeType], 80h + mov eax, [ebp+NTFS.fileDataSize] + test eax, eax + jz .resident + mov esi, [ebp+NTFS.indexOffset] + dec eax + mov [edi+lastVCN], eax + mov byte [edi+nonResidentFlag], 1 + mov byte [edi+dataRunsOffset], 40h + mov eax, [esi+fileAllocatedSize] + mov [edi+attributeAllocatedSize], eax + mov eax, [esi+fileRealSize] + mov [edi+attributeRealSize], eax + mov [edi+initialDataSize], eax + push edi + mov esi, edi + add edi, 40h + call createMcbEntry + inc edi + jmp @f + +.resident: + mov ecx, [ebp+NTFS.fileRealSize] + mov [edi+sizeWithoutHeader], ecx + mov byte [edi+attributeOffset], 18h + push edi + mov esi, [ebp+NTFS.fileDataStart] + add edi, 18h + rep movsb +@@: + mov eax, edi + pop edi + sub eax, edi + add eax, 7 + and eax, not 7 + mov [edi+sizeWithHeader], eax + add edi, eax + mov al, 1 + jmp @f + +.indexRoot: + mov byte [edi+attributeType], 90h + mov byte [edi+nameLength], 4 + mov byte [edi+nameOffset], 18h + mov byte [edi+sizeWithoutHeader], 30h + mov byte [edi+attributeOffset], 20h + mov dword[edi+18h], 490024h ; unicode $I30 + mov dword[edi+18h+4], 300033h + mov byte [edi+20h+attributeType], 30h + mov byte [edi+20h+collationRule], 1 + mov eax, [ebp+NTFS.sectors_per_cluster] + shl eax, 9 + mov [edi+20h+indexRecordSize], eax + mov byte [edi+20h+indexRecordSizeClus], 1 + mov byte [edi+30h+indexOffset], 16 + mov byte [edi+30h+nodeRealSize], 32 + mov byte [edi+30h+nodeAllocatedSize], 32 + mov byte [edi+40h+indexAllocatedSize], 16 + mov byte [edi+40h+indexFlags], 2 + add edi, 50h + mov al, 3 +@@: + mov esi, [ebp+NTFS.frs_buffer] + mov dword [edi], -1 + mov dword [edi+4], 0 + add edi, 8 + sub edi, esi + mov [ebp+NTFS.ntfs_cur_buf], esi + mov [esi+recordFlags], al + mov [esi+recordRealSize], edi + call writeRecord + test eax, eax + jnz ntfsDevice +; write MFT bitmap + mov eax, [ebp+NTFS.newMftRecord] + shr eax, 3+9 + mov ebx, eax + shl ebx, 9 + add eax, [ebp+NTFS.mftBitmapLocation] + add ebx, [ebp+NTFS.mftBitmapBuffer] + mov ecx, 1 + xor edx, edx + call fs_write64_sys + test eax, eax + jnz ntfsDevice +; 5. Write partition bitmap + cmp [ebp+NTFS.ntfsFolder], 1 + jz @f + mov eax, [ebp+NTFS.fileDataStart] + mov ecx, [ebp+NTFS.fileDataSize] + test ecx, ecx + jz @f + add ecx, eax + add ecx, 4095 + shr ecx, 3+9 + shr eax, 3+9 + sub ecx, eax + mov ebx, eax + shl ebx, 9 + add eax, [ebp+NTFS.BitmapLocation] + add ebx, [ebp+NTFS.BitmapBuffer] + xor edx, edx + call fs_write64_app + test eax, eax + jnz ntfsDevice +@@: + mov edi, [ebp+NTFS.indexOffset] + mov eax, [ebp+NTFS.newMftRecord] + mov [edi+fileRecordReference], eax +; 6. Write directory node + mov eax, [ebp+NTFS.nodeLastRead] + mov [ebp+NTFS.ntfsLastRead], eax + mov eax, [ebp+NTFS.cur_index_buf] + mov [ebp+NTFS.ntfs_cur_buf], eax + call writeRecord + mov ebx, [ebp+NTFS.fileRealSize] +ntfsDone: + mov esi, [ebp+PARTITION.Disk] + call disk_sync + call ntfs_unlock + xor eax, eax + ret + +writeRecord: +; make updateSequence and write to disk +; in: +; [ebp+NTFS.ntfs_cur_buf] -> record +; [ebp+NTFS.ntfsLastRead] = partition sector + mov esi, [ebp+NTFS.ntfs_cur_buf] + mov edi, esi + movzx ecx, word [esi+updateSequenceOffset] + add edi, ecx + mov ax, [edi] + inc ax + stosw + mov cx, [esi+updateSequenceSize] + dec ecx + push ecx +@@: + add esi, 510 + movsw + mov [esi-2], ax + dec ecx + jnz @b + mov eax, [ebp+NTFS.ntfsLastRead] + mov ebx, [ebp+NTFS.ntfs_cur_buf] + pop ecx + xor edx, edx + jmp fs_write64_sys + +createMcbEntry: +; in: +; [ebp+NTFS.fileDataStart] = position value +; [ebp+NTFS.fileDataSize] = size value +; edi -> destination +; esi -> attribute header + mov eax, [ebp+NTFS.fileDataStart] + xor edx, edx + shl eax, 1 + jnc @f + not eax +@@: + inc edx + shr eax, 8 + jnz @b + mov eax, [ebp+NTFS.fileDataSize] + shl eax, 1 + xor ecx, ecx +@@: + inc ecx + shr eax, 8 + jnz @b + lea eax, [edi+edx+1] + add eax, ecx + sub eax, esi + sub eax, [esi+sizeWithHeader] + jc @f + add word [esi+sizeWithHeader], 8 ; extend attribute + mov esi, [ebp+NTFS.frs_buffer] + mov eax, [esi+recordRealSize] + add eax, 8 + cmp [esi+recordAllocatedSize], eax + jc .end ; no space in the record + mov [esi+recordRealSize], eax + push ecx edi + add esi, eax + mov ecx, esi + sub ecx, edi + sub ecx, 8 + shr ecx, 2 + mov edi, esi + sub edi, 4 + sub esi, 12 + std + rep movsd + cld + pop edi ecx +@@: + mov eax, edx + shl eax, 4 + add eax, ecx + stosb + lea esi, [ebp+NTFS.fileDataSize] + rep movsb + lea esi, [ebp+NTFS.fileDataStart] + mov ecx, edx + rep movsb + mov [edi], cl +.end: + ret + +resizeAttribute: +; in: +; [ebp+NTFS.frs_buffer] -> file record +; [ebp+NTFS.ntfs_attr_offs] -> attribute +; edx:eax = new size +; out: +; [ebp+NTFS.fileDataSize] = clusters added (positive) +; [ebp+NTFS.fileDataStart] = added block +; CF=1 -> eax = error code + mov esi, [ebp+NTFS.ntfs_attr_offs] + mov dword [ebp+NTFS.ntfs_attr_size], eax + mov dword [ebp+NTFS.ntfs_attr_size+4], edx + cmp byte [esi+nonResidentFlag], 0 + jz .resident + mov ecx, [ebp+NTFS.sectors_per_cluster] + shl ecx, 9 + mov [esi+attributeRealSize], eax + mov [esi+attributeRealSize+4], edx + mov [esi+initialDataSize], eax + mov [esi+initialDataSize+4], edx + sub eax, 1 + sbb edx, 0 + jc .makeResident + div ecx + mov edi, eax + inc eax + mul ecx + mov [esi+attributeAllocatedSize], eax + mov [esi+attributeAllocatedSize+4], edx + mov ecx, [esi+lastVCN] + mov [esi+lastVCN], edi + movzx eax, byte [esi+dataRunsOffset] + sub edi, ecx + mov [ebp+NTFS.fileDataSize], edi + jz .done + jc .shrinkAttribute +; extend attribute + xor edi, edi + add esi, eax + push edi edi edi edi +@@: + mov edx, eax + mov eax, esi + add edi, [esp+8] + call ntfs_decode_mcb_entry + jc @b + mov [esp+4], edx + mov [esp+12], edi + add edi, [esp] + push edi + shr edi, 5 + shl edi, 2 + push eax + cmp [ebp+NTFS.ntfs_cur_iRecord], 0 + jz @f + cmp edi, [ebp+NTFS.BitmapStart] + jc .err1 +@@: + call ntfsSpaceAlloc + jc .err1 + pop edi + pop edx + cmp edx, eax + jnz .newEntry + pop edx + pop edi + pop [ebp+NTFS.fileDataStart] + mov [esp], eax + push [ebp+NTFS.fileDataSize] + add [ebp+NTFS.fileDataSize], edx + jmp @f + +.newEntry: + add esp, 12 + pop edx + push eax + push [ebp+NTFS.fileDataSize] + sub eax, edx + mov [ebp+NTFS.fileDataStart], eax +@@: + mov esi, [ebp+NTFS.ntfs_attr_offs] + call createMcbEntry + pop ecx + pop eax + jc .err2 + mov [ebp+NTFS.fileDataSize], ecx + mov [ebp+NTFS.fileDataStart], eax +.writeBitmap: + add ecx, eax + add ecx, 4095 + shr ecx, 3+9 + shr eax, 3+9 + sub ecx, eax + mov ebx, eax + shl ebx, 9 + add eax, [ebp+NTFS.BitmapLocation] + add ebx, [ebp+NTFS.BitmapBuffer] + xor edx, edx + call fs_write64_app + test eax, eax + jnz @f +.done: + ret + +.err4: + pop eax +@@: + movi eax, ERROR_DEVICE + stc + ret + +.err1: + add esp, 24 + stc +.err10: + movi eax, ERROR_DISK_FULL + ret + +.err2: + movi eax, ERROR_UNSUPPORTED_FS + ret + +.shrinkAttribute: + add ecx, edi + inc ecx + add esi, eax + xor edi, edi + sub esp, 20 +@@: + mov [esp+16], esi + call ntfs_decode_mcb_entry + jnc .err3 + add edi, [esp+8] + sub ecx, [esp] + jnc @b + mov ebx, ecx + add ecx, [esp] + mov eax, [esp+8] + mov [ebp+NTFS.fileDataSize], ecx + mov [ebp+NTFS.fileDataStart], eax + push edi + add edi, ecx + neg ebx + call ntfsSpaceFree + pop edi + jc .end +@@: + call ntfs_decode_mcb_entry + jnc .end + cmp dword[esp+8], 0 + jz @b + add edi, [esp+8] + mov ebx, [esp] + call ntfsSpaceFree + jnc @b +.end: + add esp, 16 + pop edi + cmp [ebp+NTFS.fileDataSize], 0 + jz @f + mov esi, [ebp+NTFS.ntfs_attr_offs] + call createMcbEntry + mov [ebp+NTFS.fileDataSize], 0 +@@: + ret + +.err3: + movi eax, ERROR_FS_FAIL + add esp, 20 + stc + ret + +.resident: + test edx, edx + jnz .nonResident + cmp eax, 8000h + jnc .nonResident + add ax, [esi+attributeOffset] + sub eax, [esi+sizeWithHeader] + jc @f + mov edi, [ebp+NTFS.frs_buffer] + mov ecx, eax + add ecx, [edi+recordRealSize] + cmp [edi+recordAllocatedSize], ecx + jc .nonResident + add eax, 7 + and eax, not 7 + add [edi+recordRealSize], eax + add edi, [edi+recordRealSize] + add [esi+sizeWithHeader], eax + add esi, [esi+sizeWithHeader] + mov ecx, edi + sub ecx, esi + shr ecx, 2 + sub edi, 4 + mov esi, edi + sub esi, eax + std + rep movsd + mov ecx, eax + shr ecx, 2 + xor eax, eax + rep stosd + cld + mov esi, [ebp+NTFS.ntfs_attr_offs] +@@: + mov eax, dword [ebp+NTFS.ntfs_attr_size] + mov [esi+sizeWithoutHeader], eax + mov [ebp+NTFS.fileDataSize], 0 + clc + ret + +.nonResident: ; convert resident to non-resident + mov eax, dword [ebp+NTFS.ntfs_attr_size] + sub eax, 1 + sbb edx, 0 + mov ecx, [ebp+NTFS.sectors_per_cluster] + shl ecx, 9 + div ecx + inc eax + mov [ebp+NTFS.fileDataSize], eax + mov edi, [ebp+NTFS.BitmapStart] + push ecx + call ntfsSpaceAlloc + pop ecx + jc .err10 + mov [ebp+NTFS.fileDataStart], eax + mov esi, [ebp+NTFS.ntfs_attr_offs] + xor eax, eax + xor edx, edx +@@: + add eax, ecx + inc edx + cmp eax, [esi+sizeWithoutHeader] + jc @b + push edx + push eax + stdcall kernel_alloc, eax + mov ecx, [esp] + shr ecx, 2 + mov edi, eax + mov ebx, eax + xor eax, eax + rep stosd + mov al, [esi+attributeOffset] + mov ecx, [esi+sizeWithoutHeader] + add esi, eax + mov edi, ebx + rep movsb + mov eax, [ebp+NTFS.fileDataStart] + mul [ebp+NTFS.sectors_per_cluster] + pop ecx + shr ecx, 9 + call fs_write64_app + push ebx + mov ebx, eax + call kernel_free + test ebx, ebx + jnz .err4 + mov esi, [ebp+NTFS.ntfs_attr_offs] + add esi, [esi+sizeWithHeader] + mov ecx, [ebp+NTFS.frs_buffer] + add ecx, [ecx+recordRealSize] + sub ecx, esi + shr ecx, 2 + lea edi, [ebp+NTFS.ntfs_bitmap_buf] + push ecx + rep movsd + mov edi, [ebp+NTFS.ntfs_attr_offs] + add edi, 16 + mov cl, 6 + xor eax, eax + rep stosd + mov edi, [ebp+NTFS.ntfs_attr_offs] + mov eax, [ebp+NTFS.fileDataSize] + dec eax + mov [edi+lastVCN], eax + inc eax + mov ecx, [ebp+NTFS.sectors_per_cluster] + shl ecx, 9 + mul ecx + mov byte [edi+sizeWithHeader], 50h + mov byte [edi+nonResidentFlag], 1 + mov byte [edi+dataRunsOffset], 40h + mov [edi+attributeAllocatedSize], eax + mov [edi+attributeAllocatedSize+4], edx + mov eax, dword [ebp+NTFS.ntfs_attr_size] + mov edx, dword [ebp+NTFS.ntfs_attr_size+4] + mov [edi+attributeRealSize], eax + mov [edi+attributeRealSize+4], edx + mov [edi+initialDataSize], eax + mov [edi+initialDataSize+4], edx + mov esi, edi + add edi, 40h + call createMcbEntry + mov eax, edi + mov edi, [ebp+NTFS.ntfs_attr_offs] + sub eax, edi + add eax, 8 + and eax, not 7 + mov [edi+sizeWithHeader], eax + pop ecx + lea esi, [ebp+NTFS.ntfs_bitmap_buf] + add edi, eax + rep movsd + mov esi, [ebp+NTFS.frs_buffer] + sub edi, esi + mov [esi+recordRealSize], edi + pop edx + mov ecx, [ebp+NTFS.fileDataSize] + sub [ebp+NTFS.fileDataSize], edx + mov eax, [ebp+NTFS.fileDataStart] + add [ebp+NTFS.fileDataStart], edx + jmp .writeBitmap + +.makeResident: ; convert non-resident to empty resident + movzx eax, byte [esi+dataRunsOffset] + mov byte [esi+nonResidentFlag], 0 + mov dword [esi+sizeWithoutHeader], 0 + mov dword [esi+attributeOffset], 18h + add esi, eax + xor edi, edi + sub esp, 16 +@@: + call ntfs_decode_mcb_entry + jnc @f + cmp dword[esp+8], 0 + jz @b + add edi, [esp+8] + mov ebx, [esp] + call ntfsSpaceFree + jnc @b +@@: + add esp, 16 + mov [ebp+NTFS.fileDataSize], 0 + ret + +ntfsSpaceClean: +; clean up to 16 Mb of disk space +; in: +; [ebp+NTFS.fileDataStart] = block to clean +; [ebp+NTFS.fileDataSize] = block size + mov eax, [ebp+NTFS.fileDataSize] + test eax, eax + jz @f + mul [ebp+NTFS.sectors_per_cluster] + cmp eax, 8001h + jnc @f + push eax + shl eax, 9 + stdcall kernel_alloc, eax + pop ecx + test eax, eax + jz @f + push ecx + shl ecx, 7 + mov edi, eax + mov ebx, eax + xor eax, eax + rep stosd + mov eax, [ebp+NTFS.fileDataStart] + mul [ebp+NTFS.sectors_per_cluster] + mov [ebp+NTFS.ntfsLastRead], eax + pop ecx + call fs_write64_app + stdcall kernel_free, ebx +@@: + ret + +ntfsSpaceAlloc: +; find and mark block of free space in bitmap buffer +; in: +; edi = offset in bitmap to start search from +; [ebp+NTFS.fileDataSize] = block size in clusters +; out: +; eax = allocated block starting cluster +; CF=1 -> disk full + mov ecx, [ebp+NTFS.BitmapBuffer] + add edi, ecx + add ecx, [ebp+NTFS.BitmapSize] + sub ecx, edi + jnc @f + call bitmapBuffering + shl ecx, 2 +@@: + shr ecx, 2 mov eax, [ebp+NTFS.fileDataSize] shr eax, 5 jz .small push eax ; bitmap dwords - add edi, 4 .start: - mov ecx, [ebp+NTFS.BitmapSize] - add ecx, [ebp+NTFS.BitmapBuffer] + mov ecx, [ebp+NTFS.BitmapBuffer] + add ecx, [ebp+NTFS.BitmapSize] sub ecx, edi shr ecx, 2 @@: @@ -2203,7 +2986,7 @@ ntfs_CreateFile: shl eax, 2 add esi, eax mov eax, [esi] - bsf ecx, eax ; last dword + bsf ecx, eax ; check last dword jz .done and edx, 31 cmp ecx, edx @@ -2212,10 +2995,6 @@ ntfs_CreateFile: jmp .start .small: ; less than 32 clusters - mov ecx, [ebp+NTFS.BitmapSize] - sub ecx, [ebp+NTFS.BitmapStart] - shr ecx, 2 -.smStart: mov eax, -1 repz scasd ; search for zero bits push ecx @@ -2223,7 +3002,7 @@ ntfs_CreateFile: jnz @f call bitmapBuffering pop eax - jmp .smStart + jmp .small @@: sub edi, 4 mov eax, [edi] @@ -2255,7 +3034,7 @@ ntfs_CreateFile: .again: add edi, 4 pop ecx - jmp .smStart + jmp .small .got: push ecx ; starting bit @@ -2280,7 +3059,7 @@ ntfs_CreateFile: shl eax, cl ; fits inside dword shr eax, cl or [edi], eax - jmp .writeData + jmp .end @@: or [edi], eax @@ -2297,335 +3076,86 @@ ntfs_CreateFile: shl eax, cl not eax or [edi], eax -.writeData: - pop edx - sub edx, [ebp+NTFS.BitmapBuffer] - shl edx, 3 +.end: pop eax + sub eax, [ebp+NTFS.BitmapBuffer] + shl eax, 3 + pop edx add eax, edx pop edx - mov [ebp+NTFS.fileDataStart], eax - mul [ebp+NTFS.sectors_per_cluster] - mov ecx, [ebp+NTFS.fileRealSize] - add ecx, 511 - shr ecx, 9 - mov ebx, [ebx+16] - call fs_write64_app - test eax, eax - jnz ntfsDevice - ; 4. MFT record -.mftBitmap: ; search for free record - mov edi, [ebp+NTFS.mftBitmapBuffer] - mov ecx, [ebp+NTFS.mftBitmapSize] - mov al, -1 - add edi, 3 - sub ecx, 3 - repz scasb - dec edi - movzx eax, byte [edi] - not al - bsf ecx, eax - jz ntfsUnsupported ; no free records - bts [edi], ecx -; get record location - sub edi, [ebp+NTFS.mftBitmapBuffer] - shl edi, 3 - add edi, ecx - mov [ebp+NTFS.newMftRecord], edi - mov eax, [ebp+NTFS.frs_size] - shr eax, 9 - mul edi - mov [ebp+NTFS.ntfs_cur_iRecord], 0 - mov [ebp+NTFS.ntfs_cur_attr], 0x80 - mov [ebp+NTFS.ntfs_cur_offs], eax - mov [ebp+NTFS.ntfs_cur_size], 1 - mov eax, [ebp+NTFS.frs_buffer] - mov [ebp+NTFS.ntfs_cur_buf], eax - call ntfs_read_attr - cmp [ebp+NTFS.ntfs_cur_read], 0 - jnz .mftRecord -; extend MFT $DATA - mov eax, [ebp+NTFS.mft_cluster] - mul [ebp+NTFS.sectors_per_cluster] - cmp eax, [ebp+NTFS.ntfsLastRead] - jnz ntfsUnsupported ; auxiliary record - mov edi, [ebp+NTFS.ntfs_attr_offs] - mov ebx, [ebp+NTFS.sectors_per_cluster] - shl ebx, 9+3 - add dword [edi+lastVCN], 8 - add [edi+attributeAllocatedSize], ebx - adc byte [edi+attributeAllocatedSize+4], 0 - add [edi+attributeRealSize], ebx - adc byte [edi+attributeRealSize+4], 0 - add [edi+initialDataSize], ebx - adc byte [edi+initialDataSize+4], 0 - movzx eax, byte [edi+dataRunsOffset] - add edi, eax - mov al, [edi] - inc edi - shl eax, 4 - shr al, 4 - mov cl, 4 - sub cl, al - shl cl, 3 - add ah, al - shr eax, 8 - cmp byte [edi+eax], 0 - jnz ntfsUnsupported ; $MFT fragmented - mov al, 8 - mov edx, [edi] - rol eax, cl - rol edx, cl - add eax, edx - jc ntfsUnsupported - ror eax, cl - shr edx, cl - mov [edi], eax - add edx, [ebp+NTFS.mft_cluster] - mov esi, edx - mov ecx, edx - and ecx, 7 - shr edx, 3 - add edx, [ebp+NTFS.BitmapBuffer] - mov ax, [edx] - shr ax, cl - test al, al - jnz ntfsUnsupported - dec al - xchg [edx], al - mov [edx+1], al - stdcall kernel_alloc, ebx - test eax, eax - jz ntfsNoMemory - mov ecx, ebx - shr ecx, 2 + ret + +ntfsSpaceFree: +; free disk space +; in: +; edi = starting cluster +; ebx = size in clusters + mov eax, edi + add eax, ebx + shr eax, 3 + inc eax + cmp eax, [ebp+NTFS.BitmapSize] + jc @f + add eax, [ebp+NTFS.BitmapBuffer] + push edi mov edi, eax - push ebx - mov ebx, eax + call bitmapBuffering + pop edi +@@: + push edi + mov ecx, edi + shr edi, 5 + shl edi, 2 + add edi, [ebp+NTFS.BitmapBuffer] + and ecx, 31 xor eax, eax - rep stosd - mov eax, esi - mul [ebp+NTFS.sectors_per_cluster] - pop ecx - shr ecx, 9 - call fs_write64_sys ; clear new records - stdcall kernel_free, ebx - mov eax, esi - shr eax, 3+9 - mov ebx, eax - shl ebx, 9 - add ebx, [ebp+NTFS.BitmapBuffer] - add eax, [ebp+NTFS.BitmapLocation] - mov ecx, 1 - xor edx, edx - call fs_write64_app ; partition bitmap - test eax, eax - jnz ntfsDevice - mov eax, [ebp+NTFS.frs_buffer] - mov [ebp+NTFS.ntfs_cur_buf], eax - call writeRecord ; $MFT - test eax, eax - jnz ntfsDevice - mov eax, [ebp+NTFS.mftmirr_cluster] - mul [ebp+NTFS.sectors_per_cluster] - mov ebx, [ebp+NTFS.frs_buffer] - movzx ecx, word [ebx+updateSequenceSize] - dec ecx - call fs_write64_sys ; $MFTMirr - test eax, eax - jnz ntfsDevice - mov eax, [ebp+NTFS.ntfs_cur_offs] - add [ebp+NTFS.ntfsLastRead], eax -.mftRecord: - mov esi, [ebp+NTFS.indexOffset] - mov edi, [ebp+NTFS.frs_buffer] - xor eax, eax - movzx ecx, word [esi+indexAllocatedSize] - add ecx, 8+30h+48h+50h+8 - push ecx - shr ecx, 2 - rep stosd - mov edi, [ebp+NTFS.frs_buffer] -; record header - mov dword[edi], 'FILE' - mov byte [edi+updateSequenceOffset], 2ah - mov byte [edi+updateSequenceSize], 3 - mov byte [edi+hardLinkCounter], 1 - mov byte [edi+attributeOffset], 30h - pop dword[edi+recordRealSize] - mov word [edi+recordAllocatedSize], 1024 - mov byte [edi+newAttributeID], 3 - rdtsc - mov [edi+2ah], ax - add edi, 30h -; $StandardInformation - mov byte [edi+attributeType], 10h - mov byte [edi+sizeWithHeader], 48h - mov byte [edi+sizeWithoutHeader], 30h - mov byte [edi+attributeOffset], 18h - add edi, 48h -; $FileName - mov byte [edi+attributeType], 30h - mov byte [edi+attributeID], 1 - mov cx, [esi+indexRawSize] - mov [edi+sizeWithoutHeader], ecx - mov cx, [esi+indexAllocatedSize] - add ecx, 8 - mov [edi+sizeWithHeader], ecx - mov byte [edi+attributeOffset], 18h - mov byte [edi+indexedFlag], 1 - add edi, 18h - add esi, 16 - sub ecx, 18h - shr ecx, 2 - rep movsd - cmp [ebp+NTFS.ntfsFolder], 0 - jnz @f -; $Data - mov byte [edi+attributeType], 80h - cmp [ebp+NTFS.fileRealSize], 0 - jz .zeroSize - mov esi, [ebp+NTFS.indexOffset] - mov byte [edi+nonResidentFlag], 1 - mov byte [edi+dataRunsOffset], 40h - mov eax, [esi+fileAllocatedSize] - mov [edi+attributeAllocatedSize], eax - mov eax, [esi+fileRealSize] - mov [edi+attributeRealSize], eax - mov [edi+initialDataSize], eax - mov byte [edi+40h], 44h - mov eax, [ebp+NTFS.fileDataSize] - mov [edi+41h], eax dec eax - mov [edi+lastVCN], eax - mov eax, [ebp+NTFS.fileDataStart] - mov [edi+45h], eax - mov al, 1 - jmp .writeMftRecord + shr eax, cl + shl eax, cl + neg ecx + add ecx, 32 + sub ecx, ebx + jc @f + shl eax, cl ; fits inside dword + shr eax, cl + not eax + and [edi], eax + jmp .writeBitmap -.zeroSize: - mov byte [edi+attributeOffset], 18h - mov al, 1 - jmp .writeMftRecord - -@@: ; $IndexRoot - mov byte [edi+attributeType], 90h - mov byte [edi+nameLength], 4 - mov byte [edi+nameOffset], 18h - mov byte [edi+sizeWithoutHeader], 30h - mov byte [edi+attributeOffset], 20h - mov dword[edi+18h], 490024h ; unicode $I30 - mov dword[edi+18h+4], 300033h - mov byte [edi+20h+attributeType], 30h - mov byte [edi+20h+collationRule], 1 - mov eax, [ebp+NTFS.sectors_per_cluster] - shl eax, 9 - mov [edi+20h+indexRecordSize], eax - mov byte [edi+20h+indexRecordSizeClus], 1 - mov byte [edi+30h+indexOffset], 16 - mov byte [edi+30h+nodeRealSize], 32 - mov byte [edi+30h+nodeAllocatedSize], 32 - mov byte [edi+40h+indexAllocatedSize], 16 - mov byte [edi+40h+indexFlags], 2 - mov al, 3 -.writeMftRecord: - mov byte [edi+sizeWithHeader], 50h - mov byte [edi+attributeID], 2 - mov dword[edi+50h], -1 ; $End - mov edi, [ebp+NTFS.frs_buffer] - mov [edi+recordFlags], al - mov [ebp+NTFS.ntfs_cur_buf], edi - call writeRecord - test eax, eax - jnz ntfsDevice - mov esi, [ebp+PARTITION.Disk] - call disk_sync -; write MFT bitmap - mov eax, [ebp+NTFS.newMftRecord] +@@: + not eax + and [edi], eax + neg ecx + push ecx + shr ecx, 5 + add edi, 4 + xor eax, eax + rep stosd + pop ecx + and ecx, 31 + dec eax + shr eax, cl + shl eax, cl + and [edi], eax +.writeBitmap: + pop eax + mov edi, eax + lea ecx, [eax+ebx+4095] shr eax, 3+9 - mov ebx, eax - shl ebx, 9 - add eax, [ebp+NTFS.mftBitmapLocation] - add ebx, [ebp+NTFS.mftBitmapBuffer] - mov ecx, 1 - xor edx, edx - call fs_write64_sys - test eax, eax - jnz ntfsDevice -; 5. Write partition bitmap - cmp [ebp+NTFS.ntfsFolder], 0 - jnz @f - cmp [ebp+NTFS.fileRealSize], 0 - jz @f - mov ecx, [ebp+NTFS.fileDataStart] - mov eax, ecx - add ecx, [ebp+NTFS.fileDataSize] - add ecx, 4095 shr ecx, 3+9 - shr eax, 3+9 sub ecx, eax mov ebx, eax shl ebx, 9 add eax, [ebp+NTFS.BitmapLocation] add ebx, [ebp+NTFS.BitmapBuffer] xor edx, edx - call fs_write64_app - test eax, eax - jnz ntfsDevice -@@: - mov esi, [ebp+PARTITION.Disk] - call disk_sync - mov edi, [ebp+NTFS.indexOffset] - mov eax, [ebp+NTFS.newMftRecord] - mov [edi+fileRecordReference], eax -; 6. Write directory node - mov eax, [ebp+NTFS.nodeLastRead] - mov [ebp+NTFS.ntfsLastRead], eax - mov eax, [ebp+NTFS.cur_index_buf] - mov [ebp+NTFS.ntfs_cur_buf], eax - call writeRecord - test eax, eax - jnz ntfsDevice - mov ebx, [ebp+NTFS.fileRealSize] -ntfsDone: - mov esi, [ebp+PARTITION.Disk] - call disk_sync - call ntfs_unlock - xor eax, eax - ret - -writeRecord: -; in: -; [ebp+NTFS.ntfs_cur_buf] = record -; [ebp+NTFS.ntfsLastRead] = partition sector - ; making updateSequence - mov esi, [ebp+NTFS.ntfs_cur_buf] - mov edi, esi - movzx ecx, word [esi+updateSequenceOffset] - add edi, ecx - mov ax, [edi] - add edi, 2 - mov cx, [esi+updateSequenceSize] - dec ecx - push ecx -@@: - add esi, 510 - movsw - mov [esi-2], ax - dec ecx - jnz @b -; writing to disk - mov eax, [ebp+NTFS.ntfsLastRead] - mov ebx, [ebp+NTFS.ntfs_cur_buf] - pop ecx - xor edx, edx - jmp fs_write64_sys + jmp fs_write64_app bitmapBuffering: ; Extend BitmapBuffer and read next 32kb of bitmap ; Warning: $Bitmap fragmentation is not foreseen -; if edi -> position in bitmap buffer, -; then ecx = number of buffered dwords left +; in: edi -> position in bitmap buffer +; out: ecx = number of buffered dwords left push ebx mov eax, [ebp+NTFS.BitmapTotalSize] cmp eax, [ebp+NTFS.BitmapSize] @@ -2654,11 +3184,12 @@ bitmapBuffering: jnc @f mov [ebp+NTFS.BitmapSize], eax @@: - mov ecx, [ebp+NTFS.BitmapSize] - add ecx, [ebp+NTFS.BitmapBuffer] - sub ecx, edi - shr ecx, 2 pop ebx + mov ecx, [ebp+NTFS.BitmapBuffer] + add ecx, [ebp+NTFS.BitmapSize] + sub ecx, edi + jc bitmapBuffering + shr ecx, 2 ret .err: @@ -2667,9 +3198,11 @@ bitmapBuffering: mov ecx, 8 call release_pages .end: - add esp, 12 ; double ret - push ERROR_DISK_FULL - jmp ntfsOut + pop ebx + pop eax ; ret + pop eax + stc + ret ;---------------------------------------------------------------- ntfs_WriteFile: @@ -2684,34 +3217,86 @@ ntfs_WriteFile: jc ntfsNotFound cmp [ebp+NTFS.ntfs_cur_iRecord], 16 jc ntfsDenied + bt dword [eax+fileFlags], 28 + jc ntfsDenied + cmp [ebp+NTFS.ntfsFragmentCount], 1 + jnz ntfsUnsupported ; record fragmented +; edit directory node + mov edi, [ebp+NTFS.cur_index_buf] + cmp dword [edi], 'INDX' + jz @f + mov esi, [ebp+NTFS.frs_buffer] + mov ecx, [esi+recordRealSize] + shr ecx, 2 + rep movsd + mov esi, [ebp+NTFS.ntfs_attr_offs] + mov cl, [esi+attributeOffset] + sub esi, [ebp+NTFS.frs_buffer] + add eax, ecx + add eax, esi +@@: + mov ecx, [ebx+4] + mov edx, [ebx+8] + add ecx, [ebx+12] + adc edx, 0 + mov [eax+fileRealSize], ecx + mov [eax+fileRealSize+4], edx + mov eax, [ebp+NTFS.ntfsLastRead] + mov [ebp+NTFS.nodeLastRead], eax mov [ebp+NTFS.ntfs_cur_attr], 0x80 mov [ebp+NTFS.ntfs_cur_offs], 0 mov [ebp+NTFS.ntfs_cur_size], 0 call ntfs_read_attr - jc ntfsDenied - mov eax, [ebp+NTFS.frs_buffer] - cmp word [eax+baseRecordReuse], 0 + jc ntfsFail + mov eax, ecx + mov ecx, [ebp+NTFS.frs_buffer] + cmp word [ecx+baseRecordReuse], 0 jnz ntfsUnsupported ; auxiliary record - cmp byte [eax+hardLinkCounter], 1 - jnz ntfsUnsupported ; file copying required mov ecx, [ebp+NTFS.ntfs_attr_offs] - cmp byte [ecx+nonResidentFlag], 1 - jnz ntfsUnsupported ; resident $DATA cmp word [ecx+attributeFlags], 0 jnz ntfsUnsupported - mov eax, [ebx+4] - mov edx, [ebx+8] - add eax, [ebx+12] - adc edx, 0 + push ebx + cmp byte [ecx+nonResidentFlag], 0 + jz .resizeAttribute cmp edx, [ecx+attributeRealSize+4] - jc .write - jnz ntfsUnsupported ; end of file + jc .writeNode + jnz .resizeAttribute cmp [ecx+attributeRealSize], eax - jc ntfsUnsupported -.write: + jnc .writeNode +.resizeAttribute: + call resizeAttribute + jc ntfsErrorPop + mov ecx, [ebp+NTFS.ntfs_attr_offs] + cmp byte [ecx+nonResidentFlag], 1 + jz @f + mov ebx, [esp] + movzx edi, byte [ecx+attributeOffset] + add edi, ecx + add edi, [ebx+4] + mov ecx, [ebx+12] + mov esi, [ebx+16] + rep movsb +@@: + mov eax, [ebp+NTFS.frs_buffer] + mov [ebp+NTFS.ntfs_cur_buf], eax + call writeRecord ; file + mov ebx, [ebp+NTFS.frs_buffer] + call ntfs_restore_usa_frs +.writeNode: + mov eax, [ebp+NTFS.nodeLastRead] + mov [ebp+NTFS.ntfsLastRead], eax + mov eax, [ebp+NTFS.cur_index_buf] + mov [ebp+NTFS.ntfs_cur_buf], eax + call writeRecord ; directory + pop ebx + mov ecx, [ebp+NTFS.ntfs_attr_offs] + cmp byte [ecx+nonResidentFlag], 0 + jz .done + mov ecx, [ebx+12] + test ecx, ecx + jz .done mov eax, [ebx+4] mov edx, [ebx+8] - mov ecx, [ebx+12] mov esi, [ebx+16] shrd eax, edx, 9 test dword[ebx+4], 1FFh @@ -2742,10 +3327,8 @@ ntfs_WriteFile: call fs_write64_app pop ebx pop ecx - test eax, eax - jnz ntfsDevice test ecx, ecx - jz @f + jz .done mov eax, [ebx+4] mov edx, [ebx+8] shrd eax, edx, 9 @@ -2765,7 +3348,7 @@ ntfs_WriteFile: pop ecx jc ntfsDevice and ecx, 1FFh - jz @f + jz .done add esi, [ebp+NTFS.ntfs_cur_read] mov [ebp+NTFS.ntfs_cur_size], 1 lea edi, [ebp+NTFS.ntfs_bitmap_buf] @@ -2780,9 +3363,7 @@ ntfs_WriteFile: xor edx, edx call fs_write64_app pop ebx - test eax, eax - jnz ntfsDevice -@@: +.done: mov ebx, [ebx+12] jmp ntfsDone @@ -2809,6 +3390,11 @@ ntfs_Delete: jnc ntfsUnsupported ; delete index from the node movzx edx, word [eax+indexAllocatedSize] + mov ecx, [eax+fileRecordReference] + cmp [eax+edx+fileRecordReference], ecx + jnz @f + add dx, [eax+edx+indexAllocatedSize] +@@: mov edi, [ebp+NTFS.cur_index_buf] cmp dword [edi], 'INDX' jz .indexRecord @@ -2855,8 +3441,6 @@ ntfs_Delete: mov esi, [ebp+NTFS.frs_buffer] cmp word [esi+baseRecordReuse], 0 jnz ntfsUnsupported ; auxiliary record - cmp byte [esi+hardLinkCounter], 2 - jnc .writeFileRecord ; delete hard link mov esi, [ebp+NTFS.ntfs_attr_offs] cmp byte [esi+nonResidentFlag], 0 jz .writeBitmapMFT @@ -2864,83 +3448,16 @@ ntfs_Delete: add esi, eax xor edi, edi sub esp, 16 -.clearBitmap: ; "delete" file data +@@: ; "delete" file data call ntfs_decode_mcb_entry - jnc .mcbEnd + jnc @f cmp dword[esp+8], 0 - jz .clearBitmap + jz @b add edi, [esp+8] mov ebx, [esp] - mov eax, edi - add eax, ebx - shr eax, 3 - inc eax - cmp eax, [ebp+NTFS.BitmapSize] - jc .buffered - add eax, [ebp+NTFS.BitmapBuffer] - add esp, 16 - push edi - mov edi, eax + call ntfsSpaceFree + jnc @b @@: - call bitmapBuffering - shl ecx, 2 - js @b - pop edi - sub esp, 16 -.buffered: - push edi - mov ecx, edi - shr edi, 5 - shl edi, 2 - add edi, [ebp+NTFS.BitmapBuffer] - and ecx, 31 - xor eax, eax - dec eax - shr eax, cl - shl eax, cl - neg ecx - add ecx, 32 - sub ecx, ebx - jc @f - shl eax, cl ; fits inside dword - shr eax, cl - not eax - and [edi], eax - jmp .writeBitmap - -@@: - not eax - and [edi], eax - neg ecx - push ecx - shr ecx, 5 - add edi, 4 - xor eax, eax - rep stosd - pop ecx - and ecx, 31 - dec eax - shr eax, cl - shl eax, cl - and [edi], eax -.writeBitmap: - pop edi - mov ecx, edi - add ecx, ebx - add ecx, 4095 - shr ecx, 3+9 - mov eax, edi - shr eax, 3+9 - sub ecx, eax - mov ebx, eax - shl ebx, 9 - add eax, [ebp+NTFS.BitmapLocation] - add ebx, [ebp+NTFS.BitmapBuffer] - xor edx, edx - call fs_write64_app - jmp .clearBitmap - -.mcbEnd: add esp, 16 jmp .writeBitmapMFT @@ -2971,10 +3488,8 @@ ntfs_Delete: xor edx, edx call fs_write64_sys mov esi, [ebp+NTFS.frs_buffer] - mov byte [esi+recordFlags], 0 -.writeFileRecord: - dec byte [esi+hardLinkCounter] mov [ebp+NTFS.ntfs_cur_buf], esi + mov byte [esi+recordFlags], 0 call writeRecord ; write directory node mov eax, [ebp+NTFS.nodeLastRead] @@ -2982,12 +3497,113 @@ ntfs_Delete: mov eax, [ebp+NTFS.cur_index_buf] mov [ebp+NTFS.ntfs_cur_buf], eax call writeRecord - test eax, eax - jz ntfsDone - jmp ntfsDevice + jmp ntfsDone ;---------------------------------------------------------------- ntfs_SetFileEnd: + cmp byte [esi], 0 + jnz @f + xor ebx, ebx + movi eax, ERROR_ACCESS_DENIED + ret +@@: + call ntfs_lock + stdcall ntfs_find_lfn, [esp+4] + jc ntfsNotFound + cmp [ebp+NTFS.ntfs_cur_iRecord], 16 + jc ntfsDenied + bt dword [eax+fileFlags], 28 + jc ntfsDenied + cmp [ebp+NTFS.ntfsFragmentCount], 1 + jnz ntfsUnsupported ; record fragmented +; edit directory node + mov edi, [ebp+NTFS.cur_index_buf] + cmp dword [edi], 'INDX' + jz @f + mov esi, [ebp+NTFS.frs_buffer] + mov ecx, [esi+recordRealSize] + shr ecx, 2 + rep movsd + mov esi, [ebp+NTFS.ntfs_attr_offs] + mov cl, [esi+attributeOffset] + sub esi, [ebp+NTFS.frs_buffer] + add eax, ecx + add eax, esi +@@: + mov ecx, [ebx+4] + mov edx, [ebx+8] + mov [eax+fileRealSize], ecx + mov [eax+fileRealSize+4], edx + mov eax, [ebp+NTFS.ntfsLastRead] + mov [ebp+NTFS.nodeLastRead], eax + mov [ebp+NTFS.ntfs_cur_attr], 0x80 + mov [ebp+NTFS.ntfs_cur_offs], 0 + mov [ebp+NTFS.ntfs_cur_size], 0 + call ntfs_read_attr + jc ntfsFail + mov eax, ecx + mov ecx, [ebp+NTFS.frs_buffer] + cmp word [ecx+baseRecordReuse], 0 + jnz ntfsUnsupported ; auxiliary record + mov ecx, [ebp+NTFS.ntfs_attr_offs] + cmp word [ecx+attributeFlags], 0 + jnz ntfsUnsupported + cmp byte [ecx+nonResidentFlag], 0 + jz .resizeAttribute + cmp [ecx+attributeRealSize+4], edx + jnz .resizeAttribute + cmp [ecx+attributeRealSize], eax + jnc .resizeAttribute + mov eax, [ecx+attributeRealSize] + mov ecx, [ebp+NTFS.sectors_per_cluster] + mov [ebp+NTFS.ntfs_cur_size], ecx + shl ecx, 9 + div ecx + test edx, edx + jz .aligned + push edx + push ecx + mul [ebp+NTFS.sectors_per_cluster] + mov [ebp+NTFS.ntfs_cur_offs], eax + stdcall kernel_alloc, ecx + pop ecx + pop edi + sub ecx, edi + add edi, eax + mov [ebp+NTFS.ntfs_cur_buf], eax + push [ebp+NTFS.ntfsLastRead] + call ntfs_read_attr.continue + jc @f + xor eax, eax + rep stosb + push ebx + mov eax, [ebp+NTFS.ntfsLastRead] + mov ebx, [ebp+NTFS.ntfs_cur_buf] + mov ecx, [ebp+NTFS.sectors_per_cluster] + xor edx, edx + call fs_write64_app + pop ebx +@@: + pop [ebp+NTFS.ntfsLastRead] + stdcall kernel_free, [ebp+NTFS.ntfs_cur_buf] +.aligned: + mov eax, [ebx+4] + mov edx, [ebx+8] +.resizeAttribute: + call resizeAttribute + jc ntfsError + mov eax, [ebp+NTFS.frs_buffer] + mov [ebp+NTFS.ntfs_cur_buf], eax + call writeRecord ; file + mov eax, [ebp+NTFS.nodeLastRead] + mov [ebp+NTFS.ntfsLastRead], eax + mov eax, [ebp+NTFS.cur_index_buf] + mov [ebp+NTFS.ntfs_cur_buf], eax + call writeRecord ; directory + call ntfsSpaceClean + jmp ntfsDone + +;---------------------------------------------------------------- ntfs_SetFileInfo: movi eax, ERROR_UNSUPPORTED_FS ret @@ -3018,11 +3634,7 @@ ntfs_GetFileInfo: ntfsUnsupported: push ERROR_UNSUPPORTED_FS -ntfsOut: - call ntfs_unlock - xor ebx, ebx - pop eax - ret + jmp ntfsOut ntfsDevice: push ERROR_DEVICE jmp ntfsOut @@ -3035,6 +3647,17 @@ ntfsDenied: ntfsFail: push ERROR_FS_FAIL jmp ntfsOut -ntfsNoMemory: - push ERROR_OUT_OF_MEMORY +ntfsDiskFull: + push ERROR_DISK_FULL jmp ntfsOut +ntfsErrorPop2: + pop ebx +ntfsErrorPop: + pop ebx +ntfsError: + push eax +ntfsOut: + call ntfs_unlock + xor ebx, ebx + pop eax + ret diff --git a/kernel/branches/Kolibri-acpi/init.inc b/kernel/branches/Kolibri-acpi/init.inc index dac14ff9b3..c49755bb4f 100644 --- a/kernel/branches/Kolibri-acpi/init.inc +++ b/kernel/branches/Kolibri-acpi/init.inc @@ -455,7 +455,25 @@ ACPI_FADT_SIGN equ 0x50434146 acpi_locate: push ebx + push edi + + movzx ebx, word [0x40E] + shl ebx, 4 + lea ecx, [ebx+1024] + call .check + + test ebx, ebx + jnz .done + mov ebx, ACPI_HI_RSDP_WINDOW_START + mov edi, ACPI_HI_RSDP_WINDOW_END + call .check +.done: + mov eax, ebx + pop edi + pop ebx + ret + .check: cmp [ebx], dword 0x20445352 jne .next @@ -472,17 +490,12 @@ acpi_locate: test al, al jnz .next - - mov eax, ebx - pop ebx ret .next: add ebx, 16 - cmp ebx, ACPI_HI_RSDP_WINDOW_END + cmp ebx, edi jb .check - - pop ebx - xor eax, eax + xor ebx, ebx ret align 4 diff --git a/kernel/branches/Kolibri-acpi/kernel.asm b/kernel/branches/Kolibri-acpi/kernel.asm index 5abb4428a8..cb9ce4cef6 100644 --- a/kernel/branches/Kolibri-acpi/kernel.asm +++ b/kernel/branches/Kolibri-acpi/kernel.asm @@ -253,7 +253,7 @@ B32: mov fs, ax mov gs, ax mov ss, ax - mov esp, 0x006CC00 ; Set stack + mov esp, TMP_STACK_TOP ; Set stack ; CLEAR 0x280000 - HEAP_BASE @@ -2177,7 +2177,7 @@ sys_end: @@: mov eax, [TASK_BASE] - mov [eax+TASKDATA.state], 3; terminate this program + mov [eax+TASKDATA.state], TSTATE_ZOMBIE call wakeup_osloop .waitterm: ; wait here for termination @@ -3746,7 +3746,7 @@ nobackgr: align 4 markz: push ecx edx - cmp [edx+TASKDATA.state], 9 + cmp [edx+TASKDATA.state], TSTATE_FREE jz .nokill lea edx, [(edx-(CURRENT_TASK and 1FFFFFFFh))*8+SLOT_BASE] cmp [edx+APPDATA.process], sys_proc @@ -3760,7 +3760,7 @@ markz: pop edx ecx test eax, eax jz @f - mov [edx+TASKDATA.state], byte 3 + mov [edx+TASKDATA.state], TSTATE_ZOMBIE @@: add edx, 0x20 loop markz @@ -5766,103 +5766,64 @@ yes_shutdown_param: .no_shutdown_cpus: cli + call IRQ_mask_all -if ~ defined extended_primary_loader -; load kernel.mnt to 0x7000:0 + mov eax, [OS_BASE + 0x9030] + cmp al, SYSTEM_RESTART + jne @F + +; load kernel.mnt to _CLEAN_ZONE mov ebx, kernel_file_load pushad call file_system_lfn popad - mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0 - mov edi, OS_BASE+0x40000 - mov ecx, 1000 - rep movsb -end if + mov esi, OS_BASE+restart_kernel_5000 ; move kernel re-starter to 0x5000:0 + mov edi, OS_BASE+0x50000 + mov ecx, (restart_code_end - restart_kernel_5000)/4 + rep movsd -; mov esi, BOOT_VAR ; restore 0x0 - 0xffff -; mov edi, OS_BASE -; mov ecx, 0x10000/4 -; cld -; rep movsd - - call IRQ_mask_all - - cmp byte [OS_BASE + 0x9030], 2 - jnz no_acpi_power_off - -; scan for RSDP -; 1) The first 1 Kb of the Extended BIOS Data Area (EBDA). - movzx eax, word [OS_BASE + 0x40E] - shl eax, 4 - jz @f - mov ecx, 1024/16 - call scan_rsdp - jnc .rsdp_found @@: -; 2) The BIOS read-only memory space between 0E0000h and 0FFFFFh. - mov eax, 0xE0000 - mov ecx, 0x2000 - call scan_rsdp - jc no_acpi_power_off -.rsdp_found: - mov esi, [eax+16] ; esi contains physical address of the RSDT - mov ebp, [ipc_tmp] - stdcall map_page, ebp, esi, PG_READ - lea eax, [esi+1000h] - lea edx, [ebp+1000h] - stdcall map_page, edx, eax, PG_READ - and esi, 0xFFF - add esi, ebp - cmp dword [esi], 'RSDT' - jnz no_acpi_power_off - mov ecx, [esi+4] - sub ecx, 24h - jbe no_acpi_power_off - shr ecx, 2 - add esi, 24h -.scan_fadt: - lodsd - mov ebx, eax - lea eax, [ebp+2000h] - stdcall map_page, eax, ebx, PG_READ - lea eax, [ebp+3000h] - add ebx, 0x1000 - stdcall map_page, eax, ebx, PG_READ - and ebx, 0xFFF - lea ebx, [ebx+ebp+2000h] +;disable paging + + call create_trampoline_pgmap + mov cr3, eax + jmp @F +org $-OS_BASE +@@: + mov eax, cr0 + and eax, 0x7FFFFFFF + mov cr0, eax + mov eax, cr3 + mov cr3, eax + + cmp byte [0x9030], SYSTEM_SHUTDOWN + jne no_acpi_power_off + +; system_power_off + + mov ebx, [acpi_fadt_base-OS_BASE] cmp dword [ebx], 'FACP' - jz .fadt_found - loop .scan_fadt - jmp no_acpi_power_off -.fadt_found: -; ebx is linear address of FADT - mov edi, [ebx+40] ; physical address of the DSDT - lea eax, [ebp+4000h] - stdcall map_page, eax, edi, PG_READ - lea eax, [ebp+5000h] - lea esi, [edi+0x1000] - stdcall map_page, eax, esi, PG_READ - and esi, 0xFFF - sub edi, esi - cmp dword [esi+ebp+4000h], 'DSDT' - jnz no_acpi_power_off - mov eax, [esi+ebp+4004h] ; DSDT length + jne no_acpi_power_off + mov esi, [acpi_dsdt_base-OS_BASE] + cmp dword [esi], 'DSDT' + jne no_acpi_power_off + mov eax, [esi+4] ; DSDT length sub eax, 36+4 jbe no_acpi_power_off add esi, 36 .scan_dsdt: - cmp dword [esi+ebp+4000h], '_S5_' + cmp dword [esi], '_S5_' jnz .scan_dsdt_cont - cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode + cmp byte [esi+4], 12h ; DefPackage opcode jnz .scan_dsdt_cont - mov dl, [esi+ebp+4000h+6] + mov dl, [esi+6] cmp dl, 4 ; _S5_ package must contain 4 bytes ; ...in theory; in practice, VirtualBox has 2 bytes ja .scan_dsdt_cont cmp dl, 1 jb .scan_dsdt_cont - lea esi, [esi+ebp+4000h+7] + lea esi, [esi+7] xor ecx, ecx cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx jz @f @@ -5884,21 +5845,6 @@ end if jmp do_acpi_power_off .scan_dsdt_cont: inc esi - cmp esi, 0x1000 - jb @f - sub esi, 0x1000 - add edi, 0x1000 - push eax - lea eax, [ebp+4000h] - stdcall map_page, eax, edi, PG_READ - push PG_READ - lea eax, [edi+1000h] - push eax - lea eax, [ebp+5000h] - push eax - stdcall map_page - pop eax -@@: dec eax jnz .scan_dsdt jmp no_acpi_power_off @@ -5932,34 +5878,143 @@ do_acpi_power_off: @@: jmp $ - -scan_rsdp: - add eax, OS_BASE -.s: - cmp dword [eax], 'RSD ' - jnz .n - cmp dword [eax+4], 'PTR ' - jnz .n - xor edx, edx - xor esi, esi -@@: - add dl, [eax+esi] - inc esi - cmp esi, 20 - jnz @b - test dl, dl - jz .ok -.n: - add eax, 10h - loop .s - stc -.ok: - ret - no_acpi_power_off: - call create_trampoline_pgmap - mov cr3, eax - jmp become_real+0x10000 + + jmp 0x50000 + +align 4 +restart_kernel_5000: +org 0x50000 + + cmp byte [0x9030], SYSTEM_RESTART + jne @F + + xchg bx, bx + + mov esi, _CLEAN_ZONE-OS_BASE + mov edi, 0x10000 + mov ecx, 0x31000/4 + cld + rep movsd +@@: + + xor ebx, ebx + xor edx, edx + xor ecx, ecx + xor esi, esi + xor edi, edi + xor ebp, ebp + lidt [.idt] + lgdt [.gdt] + jmp 8:@f +align 8 +.gdt: +; selector 0 - not used + dw 23 + dd .gdt + dw 0 +; selector 8 - code from 5000:0000 to 1000:FFFF + dw 0FFFFh + dw 0 + db 5 + db 10011011b + db 00000000b + db 0 +; selector 10h - data from 1000:0000 to 1000:FFFF + dw 0FFFFh + dw 0 + db 1 + db 10010011b + db 00000000b + db 0 +.idt: + dw 256*4 + dd 0 +org $ - 0x50000 +use16 +@@: + mov ax, 10h + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + mov eax, cr0 + and eax, not 80000001h + mov cr0, eax + jmp 0x5000:.real_mode + +align 4 +.real_mode: + +; setup stack + + mov ax, (TMP_STACK_TOP and 0xF0000) shr 4 + mov ss, ax + mov esp, TMP_STACK_TOP and 0xFFFF + +;remap IRQs + mov al, 0x11 + out 0x20, al + out 0xA0, al + + mov al, 0x08 + out 0x21, al + mov al, 0x70 + out 0xA1, al + + mov al, 0x04 + out 0x21, al + mov al, 0x02 + out 0xA1, al + + mov al, 0x01 + out 0x21, al + out 0xA1, al + + mov al, 0xB8 + out 0x21, al + mov al, 0xBD + out 0xA1, al + + mov al, 00110100b + out 43h, al + mov al, 0xFF + out 40h, al + out 40h, al + + mov al, byte [es:0x9030] + cmp al, SYSTEM_RESTART + je .do_restart + + jmp $ + +.do_restart: + + mov ax, 0x0003 ; set text mode for screen + int 0x10 + sti + +; (hint by Black_mirror) +; We must read data from keyboard port, +; because there may be situation when previous keyboard interrupt is lost +; (due to return to real mode and IRQ reprogramming) +; and next interrupt will not be generated (as keyboard waits for handling) + in al, 0x60 + +; bootloader interface + push 0x1000 + pop ds + mov si, kernel_restart_bootblock + mov ax, 'KL' + jmp 0x1000:0000 + + +align 4 +org restart_kernel_5000 + $ +restart_code_end: + iglobal align 4 realmode_gdt: @@ -5970,7 +6025,7 @@ realmode_gdt: ; selector 8 - code from 1000:0000 to 1000:FFFF dw 0FFFFh dw 0 - db 1 + db 5 db 10011011b db 00000000b db 0 @@ -5983,6 +6038,8 @@ realmode_gdt: db 0 endg +org $+OS_BASE + if ~ lang eq sp diff16 "end of .text segment",0,$ end if diff --git a/kernel/branches/Kolibri-acpi/network/IPv4.inc b/kernel/branches/Kolibri-acpi/network/IPv4.inc index d86322bb48..a150b89270 100644 --- a/kernel/branches/Kolibri-acpi/network/IPv4.inc +++ b/kernel/branches/Kolibri-acpi/network/IPv4.inc @@ -634,6 +634,8 @@ ipv4_output: push ecx ax edi mov eax, edi call ipv4_route ; outputs device number in edi, dest ip in eax, source IP in edx + test eax, eax + jz .no_route push edx test edi, edi jz .loopback @@ -683,6 +685,12 @@ ipv4_output: xor eax, eax ret + .no_route: + DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: No route to host!\n" + add esp, 2*4+2 + xor eax, eax + ret + .arp_error: DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax add esp, 4 @@ -917,7 +925,7 @@ endp ; ebx = outgoing device / 0 ; ; edx = Source IP ; ; ; -; OUT: eax = Destination IP (or gateway IP) ; +; OUT: eax = Destination IP (may be gateway), 0 on error ; ; edx = Source IP ; ; edi = device number*4 ; ; ; @@ -926,7 +934,7 @@ endp ; ; ;-----------------------------------------------------------------; align 4 -ipv4_route: ; TODO: return error if no valid route found +ipv4_route: test ebx, ebx jnz .got_device @@ -979,6 +987,7 @@ ipv4_route: ; TODO: return error if no valid route found ret .fail: + xor eax, eax ret diff --git a/kernel/branches/Kolibri-acpi/video/cursors.inc b/kernel/branches/Kolibri-acpi/video/cursors.inc index e6f9da6142..bb00fd8903 100644 --- a/kernel/branches/Kolibri-acpi/video/cursors.inc +++ b/kernel/branches/Kolibri-acpi/video/cursors.inc @@ -571,10 +571,11 @@ align 4 jnz @B pop edi + pop esi + ;-------------------------------------- align 4 .ret: - pop esi pop ebx ret endp @@ -605,10 +606,11 @@ align 4 jnz @B pop edi + pop esi + ;-------------------------------------- align 4 .ret: - pop esi pop ebx ret endp