• 沒有找到結果。

The Comparison of Driver Function

有了函數分類的方法,便可著手收集Device Driver的相關函數,分類並記錄對應函 數的各種屬性(Map Type),以便轉換時能有足夠的訊息判斷及處理。在本章我們把 Windows Driver一般用途(General Purpose)的函數分成十五類並找出Linux對應的函數來 探討。最後的結果會存放在資料庫,並以欄位記錄對應函數的類別、是否完全對應、Linux 函數的標頭檔以及對應的函數名稱,如Figure 13。

Figure 13: Store the Function Map in Database

5.1 Entry Function Point in Driver

Windows 將Driver所需的Entry Function利用DriverObject的變數來傳遞而Linux則 是用file物件,如Table 21所示,Windows的Entry Function被註冊在

DriverObject->MajorFunction,而Linux則是註冊在file->file_operations。此外Windows將 Driver Internal Data記錄在DeviceObject->DeviceExtension而Linux則是記錄在

file->private_data。

Windows Linux

Entry Function DriverObject->MajorFunction file->file_operations

Driver Internal Data DeviceObject->DeviceExtension; file->private_data;

Parameter will passed in Entry Function

DeviceObject、IRP file、inode, etc.

Table 21: Driver Relative Mapping Data

Windows及Linux在Kernel Mode Driver都定義一組的基本的函數,當Driver初始化時 就會註冊並呼叫這些函數,如Figure 22,一般來說整個Driver在載入及卸載的過程中會 與OS有Load、Unload、Read、Write、I/O、電源、熱插拔的問題要處理。

Windows Linux

Entry Function

DriverEntry() file_operations

Init DriverObject->DriverExtension->AddDevice XXX_init module_init(XXX_init);

Unload DriverObject->DriverUnload XXX_exit module_init(XXX_exit);

IRP_MJ_CREATE open IRP_MJ_CLOSE release

IRP_MJ_READ read4

IRP_MJ_WRITE write

IRP_MJ_PNP Minor Functions:

IRP_MN_START_DEVICE IRP_MN_QUERY_STOP_DEVICE IRP_MN_STOP_DEVICE

IRP_MN_CANCEL_STOP_DEVICE IRP_MN_QUERY_REMOVE_DEVICE IRP_MN_REMOVE_DEVICE

IRP_MN_CANCEL_REMOVE_DEVICE IRP_MN_SURPRISE_REMOVAL IRP_MN_QUERY_CAPABILITIES IRP_MN_QUERY_PNP_DEVICE_STATE

4因 Windows Driver 的 I/O 為非同步 I/O(asynchronous I/O)所以在 linux 的 file_operations 應選用 aio_write/aio_read 來對應,並在標頭檔加入<linux/aio.h>。

IRP_MJ_POWER Minor Functions:

.shutdown //power off .suspend //low power .resume //full power in <linux/device.h>.

IRP_MJ_INTERNAL_DEVICE_CONTROL Windows Exist but Linux not Exist

IRP_MJ_CLEANUP Windows Exist but Linux not Exist

IRP_MJ_QUERY_INFORMATION Windows Exist but Linux not Exist IRP_MJ_SET_INFORMATION Windows Exist but Linux not Exist IRP_MJ_SYSTEM_CONTROL Windows Exist but Linux not Exist

Windows not Exist but Linux Exist mmap

Windows not Exist but Linux Exist check_flags Windows not Exist but Linux Exist llseek Windows not Exist but Linux Exist send_file

Table 22: The Entry Function between Windows and Linux

5.2 Hardware

Windows與Linux硬體操作的函數,如Table 23所示,大部分的函數參數相同且完全 對應(Map=0)。

Map Type Include Windows Linux

0 F asm/io.h WRITE_PORT_BUFFER_UCHAR outsb 0 F asm/io.h WRITE_PORT_BUFFER_ULONG outsl 0 F asm/io.h WRITE_PORT_BUFFER_USHORT outsw

1 F asm/io.h WRITE_PORT_UCHAR outb

1 F asm/io.h WRITE_PORT_ULONG outl

1 F asm/io.h WRITE_PORT_USHORT outw

0 F asm/io.h WRITE_REGISTER_BUFFER_UCHAR iowrite8_rep 0 F asm/io.h WRITE_REGISTER_BUFFER_ULONG iowrite32_rep 0 F asm/io.h WRITE_REGISTER_BUFFER_USHORT iowrite16_rep 0 F asm/io.h WRITE_REGISTER_UCHAR iowrite8 0 F asm/io.h WRITE_REGISTER_ULONG iowrite32 0 F asm/io.h WRITE_REGISTER_USHORT iowrite16 0 F asm/io.h READ_PORT_BUFFER_UCHAR insb 0 F asm/io.h READ_PORT_BUFFER_ULONG insl 0 F asm/io.h READ_PORT_BUFFER_USHORT insw

0 F asm/io.h READ_PORT_UCHAR inb

0 F asm/io.h READ_PORT_ULONG inl

0 F asm/io.h READ_PORT_USHORT inw

0 F asm/io.h READ_REGISTER_BUFFER_UCHAR ioread8_rep 0 F asm/io.h READ_REGISTER_BUFFER_ULONG ioread32_rep 0 F asm/io.h READ_REGISTER_BUFFER_USHORT ioread16_rep 0 F asm/io.h READ_REGISTER_UCHAR ioread8 0 F asm/io.h READ_REGISTER_ULONG ioread32 0 F asm/io.h READ_REGISTER_USHORT ioread16

Table 23: The Hardware Function between Windows and Linux

以Table 24所對應的函數為例,WRITE_PORT_BUFFER_UCHARÆ outsb傳入的參 數都是一樣。

Windows Linux

Function Prototype VOID WRITE_PORT_BUFFER_UCHAR(

IN PUCHAR Port,

unsigned long count);

Token without parameter

WRITE_PORT_BUFFER_UCHAR outsb

Table 24: The Map of Port I/O Function

5.3 Reply Status

Windows與Linux的回傳值狀態的對應,如Table 25所示。Windows的狀態值被定義 在DDK的ntstatus.h,此檔定義了500多個值;而Linux則被定義在errno-base.h,只有定義 34個值。因此無法對應的部分會先行轉成-EFALUT值,再由程式設計師自行判斷調整。

Map Type Include Windows Linux

0 S linux/errno-base.h STATUS_INSUFFICIENT_RESOURCES -ENOMEM 0 S linux/errno-base.h STATUS_INVALID_PARAMETER -EINVAL 0 S linux/errno-base.h STATUS_UNSUCCESSFUL -EFAULT 0 S linux/errno-base.h STATUS_DEVICE_BUSY -EBUSY 0 S linux/errno-base.h STATUS_UNEXPECTED_IO_ERROR -EIO

0 S STATUS_SUCCESS 0

Table 25: The Reply Status between Windows and Linux

5.4 Data Type

Windows與Linux一般資料型態的函數,兩邊函數原型(Function Prototype)幾乎完全 對應(Map=0),如Table 26所示。

Map Type Include Windows Linux

0 T linux/types.h PUINT u8 *

0 T linux/types.h PUSHORT u16 *

0 T linux/types.h PULONG u32 *

0 T linux/types.h PULONGLONG u64 *

0 T linux/types.h PVOID void *

0 T linux/types.h PUCHAR unsigned char *

0 T linux/types.h PUINT unsigned int *

0 T linux/types.h PUSHORT unsigned short *

0 T linux/types.h PULONG unsigned long *

0 T linux/types.h UCHAR unsigned char

0 T linux/types.h UCHAR_PTR unsigned char *

0 T linux/types.h UINT unsigned int

0 T linux/types.h UINT_PTR unsigned int *

0 T linux/types.h USHORT unsigned short

0 T linux/types.h USHORT_PTR unsigned short *

0 T linux/types.h ULONG unsigned long

0 T linux/types.h ULONG_PTR unsigned long *

Table 26: The Data Type between Windows and Linux

5.5 Create Device Object and Set Permission

如Table 27所示,Windows使用IoCreateDevice函數來建立DeviceObject(裝置物件),

並以DeviceCharacteristics參數設定存取權限;而Linux則是使用mknod來建立一個Device File,再使用chmod指令來設定權限,。兩者的差別在於Windows將權限寫在程式裏,而 Linux是利用指令去變更存取Device File的權限。

Windows Linux

Create device file:

mknod device_file_name type major minor

Change file permission:

chmod permissions device_file_name Format

NTSTATUS IoCreateDevice(

IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize,

IN PUNICODE_STRING DeviceName OPTIONAL, IN DEVICE_TYPE DeviceType,

IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive,

OUT PDEVICE_OBJECT *DeviceObject );

DeviceObject ->Flags |= DO_DIRECT_IO;

int register_chrdev(

unsigned int major, const char * name, struct file_operations *fops

);

Driver checks any ACLs for the file name

Windows DeviceCharacteristics parameters

Linux chmod permissions parameters

Administrator/Root FILE_DEVICE_SECURE_OPEN 700

Read only FILE_READ_ONLY_DEVICE 444

Table 27: Create Device Object and Set Driver Permission

Windows與Linux註冊及解註冊Device函數,如Table 28所示。Windows的

IoCreateDevice函數會根據產生的DeviceObject其Flags值(DeviceObject ->Flags)來決定對 應到Linux的是register_chrdev/unregister_chrdev或register_blkdev/unregister_blkdev函 數,也決定Linux用mknod命令來建立device file時要使用參數c(Character Device)或 b(Block Device)的type值(咖啡色字體)。

Map Type Include Windows DeviceObject->Flags Linux

1 F linux/fs.h DO_DIRECT_IO register_chrdev

1 F linux/fs.h IoCreateDevice

DO_BUFFER_IO register_blkdev

1 F linux/fs.h DO_DIRECT_IO unregister_chrdev

1 F linux/fs.h IoDeleteDevice

DO_BUFFER_IO unregister_blkdev

Table 28: Determine I/O Type between Windows and Linux

以Table 29的例子為例,產生的裝置物件(DeviceObject)是Windows的DriverObject 對應到Linux的fops參數(紫色字體);Windows產生裝置之相關函數為IoCreateDevice及 DeviceObject ->Flags |= DO_DIRECT_IO;對應到Linux則是register_chrdev及mknod的參 數(紅色字體);裝置名稱是Windows的DeviceName對應到Linux的name參數(深藍色字 體);裝置類別在Windows指定DeviceType為FILE_DEVICE_UNKNOWN對應到Linux為 Major5參數(咖啡色字體);權限設定是Windows的FILE_DEVICE_SECURE_OPEN對應到

5在 Linux 使用 cat /proc/devices 來查看可用的 Major/Minor 值

Linux的chmod 700的permisson參數(綠色字體)。

Windows Linux

# cat /proc/devices //check major

# mknod /dev/TestDevice c 253 0

# chmod 700 /dev/TestDevice Example char devicename=”TestDevice”

status = IoCreateDevice(

DriverObject,

DeviceObject ->Flags |= DO_DIRECT_IO;

char name="TestDevice";

int major=253;

int register_chrdev(

unsigned int major, const char * name, struct file_operations *fops

);

Table 29: Create Device Function between Windows and Linux

5.6 I/O Control

在32位元的平台上,Windows與Linux對於I/O Control函數6的對應也有類似的手 法,如Table 30。Windows的DeviceType對應到Linux的type參數(紫色字體),用來表示裝 置類別,Windows的DeviceType共有16 bits,而Linux的type共有8 bits,如:

Windows: #define FILE_DEVICE_PARALLEL_PORT 0x00000016 Linux: #define 'p' 80-9F

1 F asm/ioctl.h Windows not Exist but Linux Exist #define _IO(type,nr)

1 F asm/ioctl.h

1 F asm/ioctl.h #define IOCTL_Device_Function CTL_CODE(DeviceType,

#define IOCTL_Device_Function _IOW(type,nr,size)

6 請參照 Windows DDK 及 Linux Kernel 的 Documentation/ioctl-number.txt

FunctionCode, Method,

Table 30: The I/O Control between Windows and Linux

5.7 Memory Management

Windows與Linux記憶體管理的函數,如Table 31,兩邊函數原型(Function Prototype) 幾乎完全對應。

Map Type Include Windows Linux

1 F linux/slab.h ExAllocatePool kmalloc

0 F linux/slab.h ExFreePool kfree

1 F linux/slab.h RtlZeroMemory memset 0 F asm/uaccess.h RtlCopyMemory copy_from_user 0 F asm/uaccess.h RtlMoveMemory copy_from_user 0 F linux/slab.h MmFreePagesFromMdl free_page 1 F linux/vmalloc.h MmMapIoSpace ioremap 1 F linux/vmalloc.h MmUnmapIoSpace iounmap 2 F linux/mm.h Windows not Exist but Linux Exist do_mmap

0 P linux/gfp.h NonPagedPool GFP_ATOMIC

0 P linux/gfp.h PagedPool GFP_KERNEL

Table 31: The Memory Management Function between Windows and Linux

5.8 Interrupt

Windows與Linux註冊中斷的函數,如Table 32,Linux比Windows多出許多中斷函數 來處理中斷,這部分需要程式設計師自己參酌是否需要加到程式中。

Map Type Include Windows Linux

1 F linux/interrupt.h IoConnectInterrupt request_irq 1 F linux/interrupt.h IoDisconnectInterrupt free_irq 0 P asm/signal.h In Function IoConnectInterrupt()

ShareVector=FALSE

In Function request_irq() flags=SA_INTERRUPT 0 P asm/signal.h In Function IoConnectInterrupt()

ShareVector=TRUE

In Function request_irq() flags=SA_SHIRQ

2 F linux/interrupt.h Windows not Exist but Linux Exist void local_irq_save(unsigned long flags);

2 F linux/interrupt.h Windows not Exist but Linux Exist void local_irq_disable(void);

2 F linux/interrupt.h Windows not Exist but Linux Exist void local_irq_restore(unsigned long flags);

2 F linux/interrupt.h Windows not Exist but Linux Exist void local_irq_enable(void);

2 F linux/interrupt.h Windows not Exist but Linux Exist unsigned long probe_irq_on(void);

2 F linux/interrupt.h Windows not Exist but Linux Exist int probe_irq_off(unsigned long);

2 F linux/interrupt.h Windows not Exist but Linux Exist void enable_irq(int irq);

2 F linux/interrupt.h Windows not Exist but Linux Exist void disable_irq(int irq);

Table 32: The Interrupt Function between Windows and Linux

如Table 33所示,Windows的IoConnectInterrupt/IoDisconnectInterrupt函數對應到

Windows Linux

NTSTATUS IoConnectInterrupt(

OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext,

IN PKSPIN_LOCK SpinLock OPTIONAL, IN ULONG Vector,

IN KIRQL Irql,

IN KIRQL SynchronizeIrql,

IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector,

IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave);

int request_irq(

unsigned int irq, irqreturn_t (*handler)(), unsigned long flags, const char *dev_name,

void *dev_id);

Table 33: The Interrupt Function between Windows and Linux

5.9 Synchronization

Windows與Linux的同步函數,如Table 34。Linux比Windows多出許多同步函數來處 理同步,這部分需要程式設計師自己參酌是否需要加到程式中。以取得自旋鎖(SpinLock) 為例,Windows多了一個IRQ Level的參數要輸出,而Linux沒有這樣的機制,因此轉換 時可將這部分忽略不處理。

Windows: VOID KeAcquireSpinLock(IN PKSPIN_LOCK SpinLock, OUT PKIRQL

OldIrql);

Linux: void spin_lock(spinlock_t *lock);

Map Type Include Windows Linux

0 F asm/atomic.h InterlockedIncrement atomic_inc 0 F asm/atomic.h InterlockedDecrement atomic_dec

2 F asm/atomic.h Windows not Exist but Linux Exist void atomic_set(atomic_t *v, int i);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_read(atomic_t *v);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_add(int i, atomic_t *v);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_sub(int i, atomic_t *v);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_inc(atomic_t *v);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_dec(atomic_t *v);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_inc_and_test(atomic_t *v);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_dec_and_test(atomic_t *v);

2 F asm/atomic.h Windows not Exist but Linux Exist int atomic_sub_and_test(int i, atomic_t *v);

2 F asm/bitops.h Windows not Exist but Linux Exist int set_bit(int nr, void *addr);

2 F asm/bitops.h Windows not Exist but Linux Exist int test_bit(int nr, void *addr);

2 F asm/bitops.h Windows not Exist but Linux Exist void clear_bit(int nr,void *addr);

2 F asm/bitops.h Windows not Exist but Linux Exist void change_bit(int bit, void *addr);

2 F asm/bitops.h Windows not Exist but Linux Exist int test_and_set_bit(int nr, void *addr);

2 F asm/bitops.h Windows not Exist but Linux Exist int test_and_clear_bit(nr,void *addr);

2 F asm/bitops.h Windows not Exist but Linux Exist int test_and_change_bit(int nr, void *addr);

0 T linux/types.h KSPIN_LOCK spinlock_t 0 T linux/types.h PKSPIN_LOCK spinlock_t *

3 F KeReadStateSemaphore Windows Exist but Linux not Exist

1 F KeReleaseSemaphore up

1 F KeInitializeSemaphore sema_init

1 F KeWaitForMultipleObjects down_interruptible 1 F KeWaitForSingleObject down_interruptible 0 F asm/spinlock.h KeInitializeSpinLock spin_lock_init 1 F asm/spinlock.h KeAcquireSpinLock spin_lock 1 F asm/spinlock.h KeReleaseSpinLock spin_unlock

2 F Windows not Exist but Linux Exist void spin_lock_irq(spinlock_t *lock);

2 F Windows not Exist but Linux Exist void spin_lock_bh(spinlock_t *lock);

2 F Windows not Exist but Linux Exist void spin_unlock_bh(spinlock_t *lock);

0 F KeAcquireSpinLockAtDpcLevel spin_lock 0 F KeReleaseSpinLockFromDpcLevel spin_unlock

2 F Windows not Exist but Linux Exist void init_rwsem(struct rw_semaphore *sem);

2 F Windows not Exist but Linux Exist void down_read(struct rw_semaphore *sem);

2 F Windows not Exist but Linux Exist void up_read(struct rw_semaphore *sem);

2 F Windows not Exist but Linux Exist void down_write(struct rw_semaphore *sem);

2 F Windows not Exist but Linux Exist void up_write(struct rw_semaphore *sem);

2 F Windows not Exist but Linux Exist void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);

2 F Windows not Exist but Linux Exist void spin_ulock_irqrestore(spinlock_t *lock, unsigned long flags);

Table 34: The Synchronization Function between Windows and Linux

5.10 Double Linked List

Windows與Linux的雙向鏈結函數,如Table 35所示,兩邊函數原型(Function Prototype)幾乎完全對應。

Map Type Include Windows Linux

0 F linux/list.h InitializeListHead INIT_LIST_HEAD 0 F linux/list.h InsertHeadList list_add

0 F linux/list.h InsertTailList list_add_tail 0 F linux/list.h IsListEmpty list_empty 1 F linux/list.h RemoveHeadList list_move 1 F linux/list.h RemoveTailList list_move_tail 0 T linux/list.h PLIST_ENTRY list_head * 0 T linux/list.h LIST_ENTRY list_head

Table 35: The Double Linked List Function between Windows and Linux

5.11 Timer

Windows與Linux的計時器函數,如Table 36所示。Windows平台使用KeSetTimer函 數來指定時間及回呼函數(Call Back Function)而Linux則使用timer_list的結構來存放這些 對應參數。

Map Type Include Windows Linux

0 F linux/time.h KeInitializeTimer init_timer 0 F linux/time.h KeCancelTimer del_timer

2 F linux/time.h Windows not Exist but Linux Exist int mod_timer(struct timer_list *timer, unsigned long expires);

1 F linux/time.h

BOOLEAN KeSetTimer(

IN PKTIMER Timer,

IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL );

struct timer_list TIMER_INITIALIZER(

_function, _expires, _data);

_timer.expires _timer.function

Table 36: The Timer Function between Windows and Linux

5.12 Work Thread

Windows與Linux的工作項函數,如Table 37所示。

Map Type Include Windows Linux

1 F linux/interrupt.h IoAllocateWorkItem create_workqueue 0 F linux/workqueue.h IoFreeWorkItem destroy_workqueue 1 F linux/interrupt.h IoQueueWorkItem int queue_work

3 F linux/workqueue.h IoSizeOfWorkItem Windows Exist but Linux not Exist

Table 37: The Work Thread Function between Windows and Linux

5.13 Module Description and Function Export

Module是Linux獨有但Windows沒有的函數,如Table 38所示,此部分會在轉換時加 入,程式設計師可自行調整內容。

Map Type Include Windows Linux

2 F linux/init.h Windows not Exist but Linux Exist module_init(XXX_init);

2 F linux/init.h Windows not Exist but Linux Exist module_exit(XXX_exit);

2 P Windows not Exist but Linux Exist MODULE_AUTHOR("Undefined");

2 P Windows not Exist but Linux Exist MODULE_LICENSE("GPL");

2 P Windows not Exist but Linux Exist MODULE_DESCRIPTION("Undefined");

Table 38: The Module Description is Linux Only Function

Function Export也是Linux才有的函數,如Table 39,此部分視程式設計師需要增加。

Map Type Include Windows Linux

2 F Windows not Exist but Linux Exist EXPORT_SYMBOL(name);

2 F Windows not Exist but Linux Exist EXPORT_SYMBOL_GPL(name);

Table 39: The EXPORT_SYMBOL is Linux Only Function

5.14 IRP Relative Function

在Linux沒有Irp的封包也沒有IRQ Level,如Table 40,因此這部分可忽略不必移轉

到Linux。

Map Type Include Windows Linux

3 F IoFreeIrp Windows Exist but Linux not Exist

3 F IoGetCurrentIrpStackLocation Windows Exist but Linux not Exist 3 F IoGetNextIrpStackLocation Windows Exist but Linux not Exist 3 F IoInitializeIrp Windows Exist but Linux not Exist 3 F IoMakeAssociatedIrp Windows Exist but Linux not Exist

3 F IoMapTransfer Windows Exist but Linux not Exist

3 F IoMapTransfer Windows Exist but Linux not Exist

相關文件