Mercurial > hg > Members > kono > nitros9-code
changeset 1074:2038f48c78e4
A new article on how to write extension modules
author | roug |
---|---|
date | Mon, 31 Mar 2003 18:53:23 +0000 |
parents | 43ea8e02cd96 |
children | 1e3b13dfb976 |
files | docs/articles/articles.docbook docs/articles/bootprocess.article docs/articles/extensionmodule.article docs/articles/makefile |
diffstat | 4 files changed, 498 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/docs/articles/articles.docbook Mon Mar 31 18:52:30 2003 +0000 +++ b/docs/articles/articles.docbook Mon Mar 31 18:53:23 2003 +0000 @@ -1,10 +1,12 @@ <?xml version="1.0" ?> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ - <!ENTITY tutorial SYSTEM "tutorial.article"> + <!ENTITY bootprocess SYSTEM "bootprocess.article"> + <!ENTITY ded SYSTEM "ded.article"> <!ENTITY diskcrash SYSTEM "diskcrash.article"> - <!ENTITY ded SYSTEM "ded.article"> + <!ENTITY extmodule SYSTEM "extensionmodule.article"> <!ENTITY os9software SYSTEM "os9software.article"> + <!ENTITY tutorial SYSTEM "tutorial.article"> ]> <book id="articles" lang="en"> <part label="Part One" id="part1"> @@ -19,6 +21,7 @@ <partintro> <para>How to administer OS9</para> </partintro> +&bootprocess; &diskcrash; &ded; </part> @@ -28,5 +31,6 @@ <para>How to program OS9</para> </partintro> &os9software; +&extmodule; </part> </book>
--- a/docs/articles/bootprocess.article Mon Mar 31 18:52:30 2003 +0000 +++ b/docs/articles/bootprocess.article Mon Mar 31 18:53:23 2003 +0000 @@ -1,6 +1,3 @@ -<?xml version="1.0" ?> -<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> <!-- The author has not been contacted about adding this article to the documentation set.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/articles/extensionmodule.article Mon Mar 31 18:53:23 2003 +0000 @@ -0,0 +1,490 @@ +<article> +<articleinfo> +<title>OS-9 System Extension Modules</title> +<author><firstname>Boisy</firstname> +<othername role="mi">G</othername> +<surname>Pitre</surname> +</author> +</articleinfo> +<para> +The technical information, especially in the OS-9 Level Two manuals, +is brimming with details and information that can unlock a wealth +of understanding about how OS-9 works. Unfortunately, some of this +information can be hard to digest without proper background and some +help along the way. This series of articles is intended to take a +close look at the internals of OS-9/6809, both Level One and Level Two. +So along with this article, grab your OS-9 Technical Manual, sit down +in a comfortable chair or recliner, grab a beverage, relax and let's +delve into the deep waters! +</para> +<section><title>Assemble Your Gear</title> +<para> +For successful comprehension of the topics presented +in this and future articles, I recommend that you have the following +items handy: +</para> +<itemizedlist> +<listitem><para> +OS-9 Level Two Technical Reference Manual <emphasis>or</emphasis> +</para></listitem> +<listitem><para> +OS-9 Level One Technical Information Manual (light blue book) and the +OS-9 Addendum Upgrade to Version 02.00.00 Manual +</para></listitem> +<listitem><para> +A printout of the <literal>os9defs</literal> file for your respective operating system. +This file can be found +in the DEFS directory of the OS-9 Level One Version 02.00.00 +System Master (OS-9 Level One) or the DEFS directory of +the OS-9 Development System (OS-9 Level Two). +</para></listitem> +</itemizedlist> +<para> +In this article, we will look at a rarely explored, yet intriguing OS-9 +topic: system extensions, a.k.a. P2 modules. When performing an <literal>mdir</literal> +command, you have no doubt seen modules with names like <literal>OS9p1</literal> and <literal>OS9p2</literal> +in OS-9 Level Two (or <literal>OS9</literal> and <literal>OS9p2</literal> in OS-9 Level One). These modules +are essentially the OS-9 operating system itself; they contain the +code for the system calls that are documented in the OS-9 Technical +Reference documentation. In the case of OS-9 Level One, the modules <literal>OS9</literal> +and <literal>OS9p2</literal> are located in the boot track of your boot disk (track 34). +In OS-9 Level Two, <literal>OS9p1</literal> (equivalent to the <literal>OS9</literal> module in Level One) is +found in the boot track while <literal>OS9p2</literal> is located in the bootfile. Both of +the modules are of module type <literal>Systm</literal> and define the basic behavior +and structure of OS-9. Even the module IOMan is a system extension, +containing code for the I/O calls in the operating system. +</para><para> +While drivers and file managers have been the most common area to expand +the capabilities of OS-9, they are pretty much limited to expanding the +functionality of I/O. What system extensions allow you to do is even more +powerful: they can add new system calls or even replace existing ones. +Such functionality allows you to change the behavior of OS-9 in a very +fundamental way. Of course, with such power, caution must be exercised. +It is not wise to radically modify the behavior of an existing system +call; such an action could break compatibility with existing applications. +</para><para> +What we aim to do in this article is not to replace an existing system +call, but rather to add a new system call by looking at the example +provided in Tandy's OS-9 Level Two documentation. Although the example +is written for OS-9 Level Two, we will look at how it can be changed +to run under OS-9 Level One as well. But first, let's get a little +background on system calls and how they are constructed in OS-9. +</para> +</section> +<section><title>The System Call</title> +<para> +As an operating system, OS-9 provides system level +functions, or system calls to applications. These system calls give +applications a base by which they can operate consistently and without +fear of incompatibility from one OS-9 system to the next. The system +call in OS-9/6809 evaluates to an SWI2 instruction on the 6809, which +is a software interrupt. Suffice it to say that when this instruction +is encountered by the CPU, control is routed to OS-9, which interprets +and performs the system call on behalf of the calling process. +</para><para> +While system calls are generally hidden by wrapper functions or procedures +in high-level languages such as Basic09 and C, we can see the system call +in its native form by looking at 6809 assembly language. Consider the +following assembly source fragment: +</para> +<programlisting> + lda #1 + leax mess,pcr + ldy #5 + os9 I$Write + rts +mess fcc "Hello" +</programlisting> +<para> +In the middle of what appears to be normal 6809 assembly language +source code is a mnemonic called <literal>os9</literal>. This is a pseudo mnemonic, since +Motorola did not place an <literal>os9</literal> instruction in the 6809 instruction set. +The OS-9 assembler actually recognizes this pseudo mnemonic as a special +case, along with the <literal>I$Write</literal> string, and translates the above piece of +code into: +</para> +<programlisting> + lda #1 + leax mess,pcr + ldy #5 + swi2 + fcb $8A + rts +mess fcc "Hello" +</programlisting> +<para> +The $8A which follows the <literal>swi2</literal> instruction is the constant representation +of the I/O system call <literal>I$Write</literal>. Since the <literal>swi2</literal> instruction calls into +the OS-9 kernel, the code in the kernel looks for the byte following +the <literal>swi2</literal> instruction in the module (the $8A) and interprets that as +the system call code. Using that code, OS-9 jumps to the appropriate +routine in order to execute the <literal>I$Write</literal>. +</para><para> +Since the system call code following the swi2 instruction is a byte, +in theory this would allow OS-9 to have up to 256 different system calls +that can be executed on behalf of an application. Under OS-9 Level Two, +this is the case; however under OS-9 Level One there are restrictions +placed on exactly which codes are available. The following tables show +the range of system call codes. +</para> +<table frame="all"> +<title>OS-9 Level One System Call Ranges</title> +<tgroup cols="2"> +<thead> +<row> + <entry>System call range</entry> + <entry>Function</entry> +</row> +</thead> +<tbody> +<row> + <entry>$00-$27</entry> + <entry>User mode system call codes</entry> +</row> +<row> + <entry>$29-$34</entry> + <entry>Privileged system mode call codes</entry> +</row> +<row> + <entry>$80-$8F</entry> + <entry>I/O system call codes</entry> +</row> +</tbody> +</tgroup> +</table> + +<table frame="all"> +<title>OS-9 Level Two System Call Ranges</title> +<tgroup cols="2"> +<thead> +<row> + <entry>System call range</entry> + <entry>Function</entry> +</row> +</thead> +<tbody> +<row> + <entry>$00-$7F</entry> + <entry>User mode system call codes</entry> +</row> +<row> + <entry>$80-$8F</entry> + <entry>I/O system call codes</entry> +</row> +<row> + <entry>$90-$FF</entry> + <entry>Privileged mode system call codes</entry> +</row> +</tbody> +</tgroup> +</table> +<para> +The idea behind <emphasis>User mode</emphasis> vs. <emphasis>System mode</emphasis> +is to allow two different points +of execution for the same system call, depending on whether the calling +process is running in user state or system state. OS-9 controls this +by maintaining two system call tables: one for user state and one for +system state. When installing a system call, as we'll soon see, we can +specify whether our system call should only be called from system state +(hence only updating the system table) or from both user and system state +(updating both the user and system tables). +</para><para> +An example of a system call that can be executed in both user and +privileged modes is the <literal>F$Load</literal> function code (pp. 8-25 in the OS-9 Level +Two Technical Reference manual; pp. 106 in the OS-9 Level +One Technical Information manual). Since <literal>F$Load</literal> can be called from a user +state process as well as from a driver or other module running in system +state, OS-9 installs this system call in both the user and system tables. +On the other hand, a privileged mode system call such as <literal>F$AProc</literal> (Level +Two: pp. 8-74; Level One: pp. 141) can only be called from system state +and therefore a user state process attempting to call it will receive +an error. +</para><para> +Notice that in both OS-9 Level One and OS-9 Level Two, codes $80-$8F are +reserved for I/O system call codes. When the OS-9 kernel receives one of +these codes, it passes the code along to <literal>IOMan</literal> for processing. I/O system +calls cannot be added since they are under the control of <literal>IOMan</literal>. +</para><para> +Installing a new system call involves selecting a free system call code, +determining whether the call will be accessible from both user/system +state or from system state only, and building a table in assembly language +that will be used to install the system call. Interestingly enough, +the method of installing a system call is by calling a system call! +It's called <literal>F$SSvc</literal> and is documented in your respective OS-9 Technical +manual. +</para> +</section> +<section> +<title>Installing a System Call in OS-9 Level Two</title> +<para> +The source code in Listing +1 is the system extension module, os9p3.a, which contains the code +to install the system call, as well as the system call code itself. +Incidentally, this is virtually the same code that is found in the OS-9 +Level Two Technical Reference Manual on pp. 2-2 to 2-4. I've eliminated +the comments for brevity since they are already in your manual, as well +as changed the <literal>use</literal> directive. Instead of including <literal>/dd/defs/os9defs</literal>, I +include <literal>/dd/defs/os9defs.l2</literal>. The reason for this is that I do compiling +of both OS-9 Level One and OS-9 Level Two modules on my CoCo 3 development +system. Since the OS-9 definitions are different for each operating +system, I have renamed their respective <literal>os9defs</literal> files with an extension +indicating which operating system they belong to. Even if you just develop +for one operating system or the other, I strongly suggest following the +same naming convention; it will save you headaches in the long run. +</para><para> +This module, called <literal>OS9p3</literal>, installs the <literal>F$SAYHI</literal> system call. A process +making this call can either pass a pointer to a string of up to 40 bytes +(carriage return terminated) in register X, or set X to 0, in which case +the system call will print a default message. In either case, the message +goes to the calling process' standard error path. While not very useful, +this system call is a good example of how to write a system extension. +</para><para> +The asm program is used to assemble this source code file. Notice that +the entry point for the module is the label <literal>Cold</literal>, where Y is set to the +address of the service table, <literal>SvcTbl</literal>. Each entry in this table contains +three bytes. The first is the system call code that we have selected +from a range that Microware says is safe to use for new system calls, +and the remaining two are the address of the first instruction of the +system call. The table, which can contain any number of entries, is +terminated by byte $80. After setting Y to the address of the service +table, a system call to <literal>F$SSvc</literal> is made, which takes the table pointed +to by Y and installs the system calls. +</para><para> +The code for the <literal>F$SAYHI</literal> system call in listing 1 is for OS-9 Level +Two only. It determines whether or not a valid string pointer has been +passed in register X. If indeed the caller has passed a valid pointer, +then control is routed to the label <literal>SayHi6</literal> where Y is loaded with the +maximum byte count and the process descriptor of the calling process is +used to obtain the system path number of the process' standard error +in register A. The separation of user and system state paths is an +important concept to understand; however, we will discuss it in detail +in another article. For now, let's continue analyzing the code. +</para><para> +The <literal>I$WritLn</literal> system call then prints the string at register X to the +caller's standard error path. If on the other hand, register X contains +a zero, then room is made on the caller's stack for the default message, +which is then copied into the caller's address space using the <literal>F$Move</literal> +system call. The moving of the default message from the system address +space to the caller's address space is necessary due to the separation +of a process' address space in OS-9 Level Two. +</para><para> +Once the module has been compiled, it should be included in your OS-9 +Level Two bootfile. Reboot with the new bootfile, and the <literal>OS9p2</literal> module +will find <literal>OS9p3</literal> then jump into the execution offset (the <literal>Cold</literal> label +in this case). This will install the <literal>F$SAYHI</literal> system call and make it +available for programs immediately. +</para> +</section> +<section> +<title>Installing a System Call in OS-9 Level One</title> +<para> +Listing 2 is similar to the +code in Listing 1, except that the code to move the default message +from system space to the caller's address space has been removed. Also, +the code to install the system call has changed, and the module type is +not of type <literal>Systm</literal>, but instead of type <literal>Prgrm</literal>. This is due to the lack +of separation of address space in Level One, which makes writing system +extension modules much easier than in Level Two. +</para><para> +The common address space between the system and all processes in OS-9 +Level One also makes the <literal>F$SSvc</literal> system call available from user state +as well as from system state. Unlike OS-9 Level Two, where the system +extension module must be placed in the bootfile, installing a system +extension in OS-9 Level One takes a different approach. Placing a +module called <literal>OS9p3</literal> in an OS-9 Level One bootfile will NOT cause the +system extension to be called because there are no provisions for that +in the kernel. Instead, system extensions are installed by creating a +module of type <literal>Prog</literal> that contains both code to install the system call +and the system call itself. Installing the system call entails executing +the module from the command line. +</para><para> +Besides the <literal>sayhi.a</literal> source in listing 2, another example of the this +is the <literal>Printerr</literal> command that comes with OS-9 Level One. This is a +program that actually installs a newer version of the <literal>F$PErr</literal> system call. +To install the new system call, you simply run <literal>Printerr</literal> from the command +line. It then installs the call and exits. There is an advantage to +OS-9 Level One's approach to installing system calls: it can be done +at run-time without making a new bootfile and rebooting the system. +However, additional care must be taken not to unlink the <literal>Printerr</literal> module +from memory. Why? Because the code for the replacement <literal>F$PErr</literal> call is +in that module, and if the module is unlinked, the memory it occupied +is made available subsequent reallocation and at some point, a system +crash will ensue. +</para> +</section> +<section> +<title>Exercising Our New System Call</title> +<para> +Listing 3 is a small assembly language +program, <literal>tsayhi</literal>, which calls the <literal>F$SAYHI</literal> routine. It will work fine +under both OS-9 Level One and Level Two. If you fork the <literal>tsayhi</literal> program +without any parameters, then the <literal>F$SAYHI</literal> system call is called with +register X set to $0000, which will cause the system call to print the +default message. Otherwise, you can pass a message on the command line +as a parameter and up to 40 of the message's characters will be printed +to the standard error path. +</para> +</section> +<section> +<title>Summary</title> +<para> +Extension modules give us an effective way of altering the +behavior of OS-9 by allowing us to add a new system call or modify the +behavior of an existing one. Writing extension modules requires an +extremely good understanding of the internals of OS-9. The particulars +of writing a system extension vary under OS- 9 Level One and Level Two +primarily due to the differences between memory addressing. +</para> + +<example><title>Source for os9p3.a for OS-9 Level Two</title> +<programlisting> +Type set Systm+Objct +Revs set ReEnt+1 + mod OS9End, OS9Name,Type,Revs,Cold,256 +OS9Name fcs "OS9p3" + + fcb 1 edition number + + ifp1 + use /dd/defs/os9defs.l2 + endc + +level equ 2 + opt -c + opt f + +* routine cold +Cold leay SvcTbl,pcr + os9 F$SSvc + rts + +F$SAYHI equ $25 + +SvcTbl equ * + fcb F$SAYHI + fdb SayHi-*-2 + fcb $80 + + +SayHi ldx R$X,u + bne SayHi6 + ldy D.Proc + ldu P$SP,y + leau -40,u + lda D.SysTsk + ldb P$TASK,y + ldy #40 + leax Hello,pcr + os9 F$Move + leax 0,u +SayHi6 ldy #40 + ldu D.Proc + lda P$PATH+2,u + os9 I$WritLn + rts + +Hello fcc "Hello there user." + fcb $0D + + emod + +OS9End equ * + + end +</programlisting> +</example> +<example><title>Source for sayhi.a for OS-9 Level One</title> +<programlisting> +Type set Prgrm+Objct +Revs set ReEnt+1 + mod OS9End, OS9Name,Type,Revs,Cold,256 +OS9Name fcs "SayHi" + + fcb 1 edition number + + ifp1 + use /dd/defs/os9defs.l1 + endc + +level equ 1 + opt -c + opt f + +* routine cold +Cold equ * +* The following three instructions are important. They cause the link +* count of this module to increase by 1. This insures that the module +* stays in memory, even if forked from disk. + leax OS9Name,pcr + clra + os9 F$Link + + leay SvcTbl,pcr + os9 F$SSvc + bcs Exit + clrb +Exit os9 F$Exit + +F$SAYHI equ $25 + +SvcTbl equ * + fcb F$SAYHI + fdb SayHi-*-2 + fcb $80 + +* Entry point to F$SAYHI system call +SayHi ldx R$X,u + bne SayHi6 + leax Hello,pcr +SayHi6 ldy #40 + ldu D.Proc + lda P$PATH+2,u + os9 I$WritLn + rts + +Hello fcc "Hello there user." + fcb $0D + + emod +OS9End equ * + end +</programlisting> +</example> +<example><title>Source for tsayhi.a</title> +<programlisting> +Type set Prgrm+Objct +Revs set ReEnt+1 + mod OS9End, OS9Name,Type,Revs,start,256 +OS9Name fcs "TSayHi" + + fcb 1 edition number + + ifp1 + use /dd/defs/os9defs + endc + +level equ 2 + opt -c + opt f + +F$SAYHI equ $25 + +* routine cold +start equ * + lda ,x + cmpa #$0D + bne SayHi + ldx #$0000 +SayHi os9 F$SAYHI + bcs error + clrb +error os9 F$Exit + + emod + +OS9End equ * + end +</programlisting> +</example> +</section> +</article>
--- a/docs/articles/makefile Mon Mar 31 18:52:30 2003 +0000 +++ b/docs/articles/makefile Mon Mar 31 18:53:23 2003 +0000 @@ -1,4 +1,5 @@ pdf: articles.pdf -articles.pdf: os9software.article diskcrash.article +articles.pdf: articles.docbook bootprocess.article ded.article diskcrash.article \ + os9software.article tutorial.article extensionmodule.article docbook2pdf articles.docbook