last change: Apr 26,2000
OS/2 Aurora KEE32 API
IBM is usually good for hiding easter eggs in every new (seldom
enough)
version of OS/2. While, with the OS/2 toolkit 4.5 (available through
DEVCON),
they have documented some treasures from older releases, the new
WSeB
contains, apparently for JFS, two new APIs, the KEE and the IFSM32.
The KEE is the Kernel Execution Environment, basically the
32 bit
version of what is known as the 16 bit Device Helper API known to
every
driver programmer. The following describes this API.
Unfortunately, it is not yet complete enough to allow writing pure
32 bit
physical device drivers, as several device helpers don't have a
KEE
equivalent yet (e.g. DevHlp_SetIRQ), and even worse, there is no
32 bit
driver strategy/IDC support yet, so you need at least a 16 bit
header and
some small thunk that converts the 16 bit strategy call into a
call of
a 32 bit routine in a flat segment of the driver. This is possible
and
has already been done. The KEE will supposedly greatly reduce the
effort
of writing (almost) 32 bit drivers. Currently, IBM apparently uses
KEE
in OS2DASD.DMD and JFS.IFS which are both not exactly PDDs, so
won't need
a real strategy entry point at all. See PDD, ADD, and IFS docs how
they
actually interface with the rest of the system.
Header and Lib files
To use the API, you need a 32 bit C compiler. Given the calling
conventions,
which for basically all functions require CS, DS, ES, and SS to
point to
flat kernel segments, it seems to me that finally even EMX/gcc is
suitable
for writing the 32 bit part of the driver.The KEE API
The OS/2 DDK contains a header file "bsekee.h" and an import library
"kee.lib" which you will find at the following places in the DDK
source tree:
header file: DDK\base32\rel\os2c\include\base\os2\16bit\bsekee.h
import library: DDK\base32\rel\os2c\lib\os2\kee.lib
KernAllocSpinLock
Synopsis
APIRET APIENTRY KernAllocSpinLock(KEESpinLock* sl);
Description
Initializes a spinlock to synchronize SMP processor access to a
resource.
Parameters
- sl
- Pointer to a spinlock structure in 32 bit memory.
KernFreeSpinLock
Synopsis
APIRET APIENTRY KernFreeSpinLock(KEESpinLock* sl);
Description
Destroys a spinlock structure that is no longer in use.
Parameters
- sl
- Pointer to a spinlock structure.
Comments
Actually, this routine is supposed to clear the internal "in-use"
flag.
But in 14.039SMP, it does - nothing. I think this is a bug.
KernAcquireSpinLock
Synopsis
VOID APIENTRY KernAcquireSpinLock(KEESpinLock* sl);
Description
Try to acquire the spinlock. If another processor already owns the
spinlock,
the caller will busy wait until the other owner releases the lock,
then
acquires the lock immediately.
Parameters
- sl
- Pointer to an initialized spinlock structure-
KernReleaseSpinLock
Synopsis
VOID APIENTRY KernReleaseSpinLock(KEESpinLock* sl);
Description
Release the spinlock by the current owner after use.
Parameters
- sl
- Pointer to an acquired spinlock structure.
KernAllocMutexLock
Synopsis
APIRET APIENTRY KernAllocMutexLock(KEEMutexLock* ml);
Description
Initialize a mutexlock. This is basically the semaphore equivalent
of
a spinlock. Likewise, it is usable to protect critical regions. The
difference
to a spinlock is that waiting on a mutex will send the thread that
processor
is executing to sleep. This makes sense - in contrast to a spinlock
- for
longer critical regions.
Parameters
- ml
- Pointer to a mutexlock structure in 32 bit memory.
KernFreeMutexLock
Synopsis
APIRET APIENTRY KernFreeMutexLock(KEEMutexLock* ml);
Description
Destroy a mutexlock.
Parameters
- ml
- Pointer to a mutexlock.
Comments
Likewise to KernFreeSpinLock, this is supposed to
do something, but doesn't. Again a sloppiness in code.
KernRequestSharedMutex
Synopsis
VOID APIENTRY KernRequestSharedMutex(KEEMutexLock* ml);
Description
Request a mutex in shared mode. Multiple threads may own the lock.
If a thread already owns the lock, then the calling thread will
block uninteruptibly. The block id is the address of this mutex. Use
KernTryRequestSharedMutex to attempt to acquire the mutexlock
without
blocking.
Parameters
- ml
- Pointer to a mutexlock structure.
Comments
KernReleaseSharedMutex
Synopsis
VOID APIENTRY KernReleaseSharedMutex(KEEMutexLock* ml);
Description
Give up an acquired shared mutex.
Parameters
-
-
Comments
KernTryRequestSharedMutex
Synopsis
INT APIENTRY KernTryRequestSharedMutex(KEEMutexLock* ml);
Description
Try to acquire a shared mutexlock. If this fails, 0 is returned, if
it
succeeds, the mutexlock is acquired, and 1 is returned.
Parameters
- ml
- Pointer to a mutexlock structure.
KernRequestExclusiveMutex
Synopsis
VOID APIENTRY KernRequestExclusiveMutex(KEEMutexLock* ml);
Description
Request an exclusively owned mutex. Thread will block with the
mutexlock
is already owned.
Parameters
- ml
- Pointer to exclusively owned mutexlock structure.
KernReleaseExclusiveMutex
Synopsis
VOID APIENTRY KernReleaseExclusiveMutex(KEEMutexLock* ml);
Description
Give up an owned exclusively locked structure. If there are threads
waiting,
they will be unblocked.
Parameters
- ml
- Pointer to an exclusive owned mutexlock structure.
KernTryRequestExclusiveMutex
Synopsis
INT APIENTRY KernTryRequestExclusiveMutex(KEEMutexLock* ml);
Description
Attempt to acquire an exclusive owned mutex lock. Returns 0 if the
request
failed, else 1, and the mutexlock is acquired successfully.
Parameters
- ml
- Pointer to an exclusive mutexlock.
KernBlock
Synopsis
APIRET APIENTRY KernBlock(ULONG eventid, ULONG timeout, ULONG
flags, PVOID lockptr, PULONG retdata);
Description
This is an extended version of the DevHlp_ProcBlock function.
Basically, you specify an arbitrary eventid and a timeout. The block
may be coordinated
with either an acquired spinlock or a mutexlock, as declared by the
flags.
The lock is released immediately before blocking, and reacquired
after
returning from the routine, unless the flag bit KEE_BLOCK_NOACQUIRE
prevents re-acquiration. The blocked thread will hang in this
routine, and can be resurrected by a signal (unless turned off with
KEE_BLOCK_NOSIGNALS)
or a KernWakeup with the same eventid.
Parameters
- eventid
- Some unique value, which is to be used by KernWakeup to
unblock the
thread again.
- timeout
- a timeout value in milliseconds. 0xffffffff is supposedly
infinite wait.
- flags
- One or more of the following flags:
- KEE_BLOCK_NOSIGNALS
- Ignore signals, i.e. the block can be released only by end
of timeout
or an explicit wakeup.
- KEE_BLOCK_SPINLOCK
- The lockptr points to an acquired KEESpinLock structure.
- KEE_BLOCK_EXMUTEXLOCK
- The lockptr points to an acquired exclusive mutexlock
structure.
- KEE_BLOCK_SHMUTEXLOCK
- The lockptr points to an acquired shared mutexlock
structure.
- KEE_BLOCK_NOACQUIRE
- Don't reacquire the lock (if lockptr points to a lock at
all) when the
KernBlock routine returns.
- lockptr
- Used when one of the three *LOCK bits is set: points to the
specified
lock structure
- retdata
- points to a long variable that receives the value passed by
the KernWakeup
routine. May be NULL, in this case the value is ignored.
Comments
The KEE_NOSIGNALS bit looks dangerous to me - you can this way
easily
produce unkillable processes: Block in an ioctl with this bit set,
and a
bug preventing the wakeup, and you won't get rid of this process
anymore.
The three *LOCK bits are exclusive since there is only one pointer.
I guess the retdata value us irrelevant for a timeout or an
interrupt
by a signal (return values ERROR_TIMEOUT and ERROR_INTERRUPT).
KernWakeup
Synopsis
APIRET APIENTRY KernWakeup(ULONG eventid, ULONG flags, PULONG
tcnt, ULONG retdata);
Description
This wakes up threads that are blocking in KernBlock. The eventid to
be specified
has to match the eventid used in KernBlock. It is possible to submit
a 32 bit
return value to the unblocked thread. The number of threads that are
unblocked
is returned.
must match
Parameters
- eventid
- Event id of the blocked thread(s).
- flags
- One or more of the following flag bits:
- KEE_WAKE_SINGLE
- Only wakeup the first matching thread; by default, if
multiple threads
are waiting, all will be awaking.
- KEE_WAKE_PRIOINCR
- Run the woke threads with higher priority.
- KEE_WAKE_RETDATA
- return data value specified to the KernBlock retdata
variable. By default,
nothing is returned.
- tcnt
- pointer to an ULONG to return the actual number of threads
that were woke.
Ignored when NULL.
- retdata
- Data to be returned to the unblocked threads. Ignored when
KEE_WAKE_RETDATA
is not set.
Comments
I don't know whether the priority increase issued by
KEE_WAKE_PRIOINCR is
permanent, or only for the current timeslice. It shouldn't be
permanent.
KernThunkStackTo16
Synopsis
VOID APIENTRY KernThunkStackTo16(VOID);
Description
This will convert a 16:32 SS:ESP value to a 16:16 SS:SP value.
Parameters
None.
Comments
I think this is required for correct calling of 16 bit code from the
32 bit
driver, as 16 bit drivers assume a 16:16 stackpointer.
KernThunkStackTo32
Synopsis
VOID APIENTRY KernThunkStackTo32(VOID);
Description
This will convert a 16:16 SS:SP back to the 16:32 SS:ESP convention.
Parameters
None.
Comments
This is supposedly to be called after returning from 16 bit code.
KernSerialize16BitDD
Synopsis
VOID APIENTRY KernSerialize16BitDD(VOID);
Description
This will acquire a special kernel spinlock.
Parameters
None.
Comments
I think, according to the name, this has to be called before
accessing a
16 bit driver. I wonder though, since you supposedly also have to
adjust
the stack pointer (KernThunkStackTo16), why both functions haven't
been
joined in a single call.
KernUnserialize16BitDD
Synopsis
VOID APIENTRY KernUnserialize16BitDD(VOID);
Description
This releases a special kernel spinlock.
Parameters
None.
Comments
See comments for KernSerialize16BitDD. This apparently needs to be
called
after returning from a 16 bit driver.
KernArmHook
Synopsis
VOID APIENTRY KernArmHook(ULONG hook,ULONG data);
Description
This is the 32 bit equivalent of DevHlp_ArmCtxHook.
Parameters
- hook
- Hook as returned from KernAllocateContextHook.
- data
- Data that is passed to the hook when called.
Comments
There is no such thing as a DevHlp_FreeCtxHook. I am unsure whether
the
hook handles are portable between 16 and 32 bit code. At least, this
demonstrates that the KEE API has been tailored straight to its use
in
JFS and DASD, where one probably never needs to release a hook
again.
KernAllocateContextHook
APIRET APIENTRY KernAllocateContextHook(PVOID pfHandler,ULONG
dummy, PULONG pHook);
Synopsis
Description
Allocate a new Context hook for use with KernArmHook.
Parameters
- pfHandler
- This is the address of the hook handler. This is likely a
pointer to a 32 bit function.
- dummy
- I don't know why this is there, it is never accessed in the
code.
- pHook
- The pointer to an ULONG where the hook handle is returned.
Comments
See comments for KernArmHook.
KernCopyIn
Synopsis
APIRET APIENTRY KernCopyIn(PVOID trgt, PVOID src, ULONG size);
Description
Copy a buffer of user space data into a kernel buffer.
Parameters
- trgt
- Target buffer address in kernel space.
- src
- Source buffer address in user space.
- size
- number of bytes to copy.
Comments
Finally, the routine I have waited for for eons...
KernCopyOut
Synopsis
APIRET APIENTRY KernCopyOut(PVOID trgt, PVOID src, ULONG
size);
Description
Copy a buffer of kernel data into a user space buffer.
Parameters
- trgt
- Target buffer in user space.
- src
- Source buffer in kernel space.
- size
- number of bytes to copy.
KernVMAlloc
Synopsis
APIRET APIENTRY KernVMAlloc(ULONG size, ULONG flags, PVOID*
linaddr, PVOID* physaddr, PSHORT sel);
Description
This is the equivalent of the DevHlp_VMAlloc function.
Parameters
- size
- Number of bytes to allocate.
- flags
- One or more of the following flags. See DevHlp_VMAlloc docs
for details.
- KEE_VMA_16MB
- allocate memory from below 16MB
- KEE_VMA_FIXED
- allocate memory that won't be swapped out
- KEE_VMA_SWAP
- allocate memory that is swappable
- KEE_VMA_CONTIG
- allocate contiguous physical memory pages
- KEE_VMA_PHYS
- allocate physical memory (pass address in physaddr
argument)
- KEE_VMA_PROCESS
- allocate memory in the process address space.
- KEE_VMA_SGSCONT
- register memory under screen group control
- KEE_VMA_GETSEL
- return a GDT selector for the allocated memory. This
option exists also
in DevHlp_VMAlloc (undocumented).
- KEE_VMA_RESERVE
- Don't commit the allocated memory.
- KEE_VMA_SHARED
- allocate memory that is shareable
- KEE_VMA_USEHIGHMEM
- allocate memory from above 16MB.
- linaddr
- address of a variable to receive the linear address of the
memory.
- physaddr
- address of a variable that contains the physical address of
the memory.
- sel
- address of a variable to receive the allocated GDT selector,
when KEE_VMA_GETSEL
is set.
KernVMFree
Synopsis
APIRET APIENTRY KernVMFree(PVOID linaddr);
Description
This frees dynamic memory allocated with KernVMAlloc.
Parameters
- linaddr
- Address of allocated memory.
KernVMLock
Synopsis
APIRET APIENTRY KernVMLock(ULONG flags,PVOID linaddr,ULONG
size, KEEVMLOCK* lock, KEEVMPageList* pglist, PULONG pgsize);
Description
This is the equivalent of the DevHlp_VMLock function. See the PDD
docs for details.
Parameters
- flags
- One or more of the following bits:
- KEE_VML_NOTBLOCK
- Don't block the call, if the pages can't be locked.
- KEE_VML_CONTIG
- Pages locked must be contiguous.
- KEE_VML_16M
- Pages must be below 16MB.
- KEE_VML_WRITEABLE
- Pages will be writeable.
- KEE_VML_LONGLOCK
- The lock is for long time.
- KEE_VML_VERIFYONLY
- Verify the accessibility of the region. If
KEE_VML_WRITEABLE is set, check for R/W access, else R/O.
- linaddr
- linear address of the memory region.
- size
- Size of the memory region.
- lock
- Pointer to a lock data structure that contains the lock
information.
- pglist
- Pointer to a pagelist structure, provided by the user
- pgsize
- Pointer to an ULONG where the size of the pagelist structure
is
returned.
KernVMUnlock
Synopsis
APIRET APIENTRY KernVMUnlock(KEEVMLOCK* lock);
Description
Unlock a memory region.
Parameters
- lock
- Pointer to the lock structure used by KernVMLock.
KernLinToPageList
Synopsis
APIRET APIENTRY KernLinToPageList(PVOID linaddr,ULONG
size,KEEVMPageList* list,PULONG pgsize);
Description
Convert a linear address region to a pagelist. This is the
equivalent to
DevHlp_LinToPageList.
Parameters
- linaddr
- Address of the linear region
- size
- Length of the linear region
- list
- Address of an array of pagelist elements long enough to
receive the
pagelist entries.
- pgsize>
- Pointer to an ULONG that contains the number of pagelist
entries that were actually stored.
KernVMSetMem
Synopsis
APIRET APIENTRY KernVMSetMem(ULONG flags, PVOID linaddr, ULONG
size);
Description
This is the equivalent of the DevHlp_VMSetMem function.
Parameters
- flags
- One or more of the following flags:
- KEE_VMS_UNCOMMIT
- Uncommit the region
- KEE_VMS_RESIDENT
- make the region resident
- KEE_VMS_SWAPPABLE
- make the region swappable
- linaddr
- Linear address of region
- size
- Size of region
KernSelToFlat
Synopsis
ULONG KernSelToFlat(ULONG addr16);
Description
Convert a 16:16 address to a flat address. Returns the linear flat
address.
Parameters
- addr16
- 16:16 pointer
KernDynamicAPI
Synopsis
APIRET APIENTRY KernDynamicAPI(PVOID addr, ULONG cnt, ULONG
dummy, PUSHORT sel);
Description
This is the equivalent of the DevHlp_DynamicAPI function.
Parameters
- addr
- Address of the routine to be called through this gate.
- cnt
- Number of arguments to be copied from user stack to kernel
stack
- dummy
- I don't know what this parameter is for. It is not used in the
code.
- sel
- Pointer to a variable where the generated GDT gate selector is
returned
KernRASSysTrace
Synopsis
APIRET APIENTRY KernRASSysTrace(ULONG major,ULONG minor,PVOID
buf, ULONG size);
Description
This is the equivalence of the DevHlp_RASTrace function.
Parameters
- major
- Major number of RAS event
- minor
- Minor number of RAS event
- buf
- buffer to be added to the RAS log
- size
- size of the buffer
Comments
This is not explained in the PDD reference manual, but in the debug
handbook
IIRC. Warning: The buffer is assumed to be allocated on the task
stack, not
as a global variable or a VMAlloc'd memory area.
KernPerfSysTrace
Synopsis
APIRET APIENTRY KernPerfSysTrace(ULONG major,ULONG minor,PVOID
buf, ULONG size);
Description
This is the equivalent of the DevHlp_Perftrace function used by
PerfView.
Parameters
- major
- Major number of Perf event
- minor
- Minor number of Perf event
- buf
- buffer to be added to the Perf log
- size
- size of the buffer
Comments
Warning: The buffer is assumed to be allocated on the task stack,
not
as a global variable or a VMAlloc'd memory area.
KernLockFile
Synopsis
APIRET APIENTRY KernLockFile(HFILE hfd,KEEhfile* khfd);
Description
This function converts a user space file handle to a system file
table
pointer.
Parameters
- hfd
- User space file handle
- khfd
- Pointer to an variable to return the SFT entry pointer.
Comments
This is some sort of DosOpen to access user files. This seems to be
a kludge
required for some feature of JFS.
KernUnLockFile
Synopsis
APIRET APIENTRY KernUnLockFile(KEEhfile khfd);
Description
This will return the specified SFT pointer to the system.
Parameters
- khfd
- SFT pointer.
Comments
This is some sort of DosClose after a file has been opened with
KernLockFile.
KernGetFileSize
Synopsis
APIRET APIENTRY KernGetFileSize(KEEhfile khfd,KEEfilesize*
sz);
Description
This returns the size of the file designated by KernLockFile.
Parameters
- khfd
- SFT pointer
- Address of a double long variable to hold the size of the
file.
-
Comments
Like the other SFT related functions, this seems to be a hack for
JFS.
KernTestFileCache
Synopsis
APIRET APIENTRY KernTestFileCache(KEEhfile khfd);
Description
Check whether the associated IFS for the specified file allows
access to
the file cache. Return 1 if yes, 0 if not. This seems to be again a
special
feature for JFS.
Parameters
- khfd
- SFT pointer
KernReadFileAt
APIRET APIENTRY KernReadFileAt(KEEhfile khfd,PVOID buf, QWORD
off, ULONG nbytes, PULONG nread);
Synopsis
Description
This reads the content of a file into a buffer.
Parameters
- khfd
- SFT pointer
- buf
- buffer to read data into
- off
- Offset in file to start reading
- nbytes
- Number of bytes to read
- nread
- Pointer to an ULONG to receive the number of bytes actually
read.
Comments
KernReadFileAtCache
APIRET APIENTRY KernReadFileAtCache(KEEhfile
khfd,KEECachePages** ptr, QWORD off, ULONG nbytes, PULONG nread);
Synopsis
Description
This seems to do the same as KernReadAtFile, but reads from the
cache and
returns the corresponding pages of the cache data structure.
Parameters
- khfd
- SFT pointer
- ptr
- Pointer to a variable the receives the cache data structure
for the
specified data blocks.
- off
- Offset in file to start reading
- nbytes
- Number of bytes to read
- nread
- Pointer to an ULONG to receive the number of bytes actually
read.
Comments
Yet another JFS hack. Meanwhile I understand why IBM is reluctant to
provide JFS support for Warp 4.
KernReturnFileCache
Synopsis
APIRET APIENTRY KernReturnFileCache(KEEhfile
khfd,KEECachePages* ptr);
Description
This appears to be the "free" function to return the ptr structure
from
KernReadFileAtCache back to the system.
Parameters
- khfd
- SFT pointer
- ptr
- Pointer to a previously received cache data structure.
KernCreateUconvObject
Synopsis
APIRET APIENTRY KernCreateUconvObject(USHORT codepage,
KEEUnicodeStruct* ucs);
Description
This initializes a data structure related to Unicode conversion.
Parameters
- codepage
- Codepage for the data structure.
- ucs
- Pointer to the unicode conversion structure created.
Comments
Finally, this seems to be Unicode support in the kernel...
KernStrFromUcs
Synopsis
APIRET APIENTRY KernStrFromUcs(KEEUnicodeStruct* ucs, PCHAR
trgt, PCHAR usrc, ULONG trgtsize, ULONG srcsize);
Description
This converts a string from Unicode to ASCII.
Parameters
- ucs
- Pointer to the Unicode conversion object created with
KernCreateUconvObject.
- trgt
- Pointer to the ASCII buffer
- usrc
- Pointer to the Unicode buffer
- trgtsize
- length of the target buffer
- srcsize
- length of the source buffer
KernStrToUcs
Synopsis
APIRET APIENTRY KernStrToUcs(KEEUnicodeStruct* ucs, PCHAR
utrgt, PCHAR src, ULONG trgtsize,ULONG srcsize);
Description
This converts a string from ASCII to Unicode.
Parameters
- ucs
- Pointer to the Unicode conversion object created with
KernCreateUconvObject.
- utrgt
- Pointer to the Unicode buffer
- src
- Pointer to the ASCII buffer
- trgtsize
- length of the target buffer
- srcsize
- length of the source buffer