summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--sos-code-article1/INSTALL118
-rw-r--r--sos-code-article1/LICENSE340
-rw-r--r--sos-code-article1/Makefile52
-rw-r--r--sos-code-article1/README90
-rw-r--r--sos-code-article1/VERSION11
-rw-r--r--sos-code-article1/bootstrap/multiboot.S74
-rw-r--r--sos-code-article1/bootstrap/multiboot.h129
-rw-r--r--sos-code-article1/cdrom/boot/grub/menu.lst3
-rw-r--r--sos-code-article1/cdrom/boot/grub/stage2_eltoritobin0 -> 147440 bytes
-rwxr-xr-xsos-code-article1/cdrom/sos.elfbin0 -> 13687 bytes
-rw-r--r--sos-code-article1/drivers/bochs.c119
-rw-r--r--sos-code-article1/drivers/bochs.h54
-rw-r--r--sos-code-article1/drivers/x86_videomem.c128
-rw-r--r--sos-code-article1/drivers/x86_videomem.h98
-rw-r--r--sos-code-article1/extra/Makefile40
-rw-r--r--sos-code-article1/extra/README73
-rw-r--r--sos-code-article1/extra/bootsect.S393
-rw-r--r--sos-code-article1/extra/dot.mkvars29
-rw-r--r--sos-code-article1/extra/grub.img.gzbin0 -> 67535 bytes
-rw-r--r--sos-code-article1/extra/mtoolsrc2
-rw-r--r--sos-code-article1/extra/qemu-port-e9.diff73
-rw-r--r--sos-code-article1/extra/sos_bsect.lds61
-rw-r--r--sos-code-article1/hwcore/ioports.h47
-rwxr-xr-xsos-code-article1/sos.elfbin0 -> 13687 bytes
-rw-r--r--sos-code-article1/sos.map33
-rw-r--r--sos-code-article1/sos/assert.h42
-rw-r--r--sos-code-article1/sos/errno.h39
-rw-r--r--sos-code-article1/sos/klibc.c271
-rw-r--r--sos-code-article1/sos/klibc.h84
-rw-r--r--sos-code-article1/sos/main.c69
-rw-r--r--sos-code-article1/sos/types.h42
-rwxr-xr-xsos-code-article1/support/build_image.sh215
-rw-r--r--sos-code-article1/support/sos.lds107
-rw-r--r--sos-code-article2/INSTALL118
-rw-r--r--sos-code-article2/LICENSE340
-rw-r--r--sos-code-article2/Makefile56
-rw-r--r--sos-code-article2/README90
-rw-r--r--sos-code-article2/VERSION11
-rw-r--r--sos-code-article2/bootstrap/multiboot.S74
-rw-r--r--sos-code-article2/bootstrap/multiboot.h129
-rw-r--r--sos-code-article2/cdrom/boot/grub/menu.lst3
-rw-r--r--sos-code-article2/cdrom/boot/grub/stage2_eltoritobin0 -> 147440 bytes
-rwxr-xr-xsos-code-article2/cdrom/sos.elfbin0 -> 22391 bytes
-rw-r--r--sos-code-article2/drivers/bochs.c119
-rw-r--r--sos-code-article2/drivers/bochs.h54
-rw-r--r--sos-code-article2/drivers/x86_videomem.c128
-rw-r--r--sos-code-article2/drivers/x86_videomem.h98
-rw-r--r--sos-code-article2/extra/Makefile40
-rw-r--r--sos-code-article2/extra/README73
-rw-r--r--sos-code-article2/extra/bootsect.S393
-rw-r--r--sos-code-article2/extra/dot.mkvars29
-rw-r--r--sos-code-article2/extra/grub.img.gzbin0 -> 67535 bytes
-rw-r--r--sos-code-article2/extra/mtoolsrc2
-rw-r--r--sos-code-article2/extra/qemu-port-e9.diff73
-rw-r--r--sos-code-article2/extra/sos_bsect.lds61
-rw-r--r--sos-code-article2/hwcore/exception.c92
-rw-r--r--sos-code-article2/hwcore/exception.h80
-rw-r--r--sos-code-article2/hwcore/exception_wrappers.S197
-rw-r--r--sos-code-article2/hwcore/gdt.c150
-rw-r--r--sos-code-article2/hwcore/gdt.h41
-rw-r--r--sos-code-article2/hwcore/i8254.c80
-rw-r--r--sos-code-article2/hwcore/i8254.h36
-rw-r--r--sos-code-article2/hwcore/i8259.c80
-rw-r--r--sos-code-article2/hwcore/i8259.h41
-rw-r--r--sos-code-article2/hwcore/idt.c160
-rw-r--r--sos-code-article2/hwcore/idt.h85
-rw-r--r--sos-code-article2/hwcore/ioports.h47
-rw-r--r--sos-code-article2/hwcore/irq.c91
-rw-r--r--sos-code-article2/hwcore/irq.h74
-rw-r--r--sos-code-article2/hwcore/irq_wrappers.S173
-rw-r--r--sos-code-article2/hwcore/segment.h59
-rwxr-xr-xsos-code-article2/sos.elfbin0 -> 22391 bytes
-rw-r--r--sos-code-article2/sos.map106
-rw-r--r--sos-code-article2/sos/assert.h42
-rw-r--r--sos-code-article2/sos/errno.h39
-rw-r--r--sos-code-article2/sos/klibc.c271
-rw-r--r--sos-code-article2/sos/klibc.h84
-rw-r--r--sos-code-article2/sos/main.c152
-rw-r--r--sos-code-article2/sos/types.h45
-rwxr-xr-xsos-code-article2/support/build_image.sh215
-rw-r--r--sos-code-article2/support/sos.lds107
-rw-r--r--sos-code-article3/INSTALL118
-rw-r--r--sos-code-article3/LICENSE340
-rw-r--r--sos-code-article3/Makefile44
-rw-r--r--sos-code-article3/README90
-rw-r--r--sos-code-article3/VERSION11
-rw-r--r--sos-code-article3/bootstrap/multiboot.S74
-rw-r--r--sos-code-article3/bootstrap/multiboot.h129
-rw-r--r--sos-code-article3/drivers/bochs.c119
-rw-r--r--sos-code-article3/drivers/bochs.h54
-rw-r--r--sos-code-article3/drivers/x86_videomem.c128
-rw-r--r--sos-code-article3/drivers/x86_videomem.h98
-rw-r--r--sos-code-article3/extra/Makefile40
-rw-r--r--sos-code-article3/extra/README73
-rw-r--r--sos-code-article3/extra/bootsect.S393
-rw-r--r--sos-code-article3/extra/dot.mkvars29
-rw-r--r--sos-code-article3/extra/grub.img.gzbin0 -> 67535 bytes
-rw-r--r--sos-code-article3/extra/mtoolsrc2
-rw-r--r--sos-code-article3/extra/qemu-port-e9.diff73
-rw-r--r--sos-code-article3/extra/sos_bsect.lds61
-rw-r--r--sos-code-article3/hwcore/exception.c92
-rw-r--r--sos-code-article3/hwcore/exception.h80
-rw-r--r--sos-code-article3/hwcore/exception_wrappers.S197
-rw-r--r--sos-code-article3/hwcore/gdt.c150
-rw-r--r--sos-code-article3/hwcore/gdt.h41
-rw-r--r--sos-code-article3/hwcore/i8254.c80
-rw-r--r--sos-code-article3/hwcore/i8254.h36
-rw-r--r--sos-code-article3/hwcore/i8259.c80
-rw-r--r--sos-code-article3/hwcore/i8259.h41
-rw-r--r--sos-code-article3/hwcore/idt.c160
-rw-r--r--sos-code-article3/hwcore/idt.h85
-rw-r--r--sos-code-article3/hwcore/ioports.h47
-rw-r--r--sos-code-article3/hwcore/irq.c91
-rw-r--r--sos-code-article3/hwcore/irq.h74
-rw-r--r--sos-code-article3/hwcore/irq_wrappers.S173
-rw-r--r--sos-code-article3/hwcore/segment.h59
-rw-r--r--sos-code-article3/sos/assert.h42
-rw-r--r--sos-code-article3/sos/errno.h40
-rw-r--r--sos-code-article3/sos/klibc.c271
-rw-r--r--sos-code-article3/sos/klibc.h84
-rw-r--r--sos-code-article3/sos/list.h186
-rw-r--r--sos-code-article3/sos/macros.h37
-rw-r--r--sos-code-article3/sos/main.c236
-rw-r--r--sos-code-article3/sos/physmem.c269
-rw-r--r--sos-code-article3/sos/physmem.h119
-rw-r--r--sos-code-article3/sos/types.h50
-rwxr-xr-xsos-code-article3/support/build_image.sh215
-rw-r--r--sos-code-article3/support/sos.lds107
-rw-r--r--sos-code-article4/INSTALL118
-rw-r--r--sos-code-article4/LICENSE340
-rw-r--r--sos-code-article4/Makefile45
-rw-r--r--sos-code-article4/README90
-rw-r--r--sos-code-article4/VERSION11
-rw-r--r--sos-code-article4/bootstrap/multiboot.S74
-rw-r--r--sos-code-article4/bootstrap/multiboot.h129
-rw-r--r--sos-code-article4/drivers/bochs.c119
-rw-r--r--sos-code-article4/drivers/bochs.h54
-rw-r--r--sos-code-article4/drivers/x86_videomem.c128
-rw-r--r--sos-code-article4/drivers/x86_videomem.h98
-rw-r--r--sos-code-article4/extra/Makefile40
-rw-r--r--sos-code-article4/extra/README73
-rw-r--r--sos-code-article4/extra/bootsect.S393
-rw-r--r--sos-code-article4/extra/dot.mkvars29
-rw-r--r--sos-code-article4/extra/grub.img.gzbin0 -> 67535 bytes
-rw-r--r--sos-code-article4/extra/mtoolsrc2
-rw-r--r--sos-code-article4/extra/qemu-port-e9.diff73
-rw-r--r--sos-code-article4/extra/sos_bsect.lds61
-rw-r--r--sos-code-article4/hwcore/exception.c92
-rw-r--r--sos-code-article4/hwcore/exception.h80
-rw-r--r--sos-code-article4/hwcore/exception_wrappers.S197
-rw-r--r--sos-code-article4/hwcore/gdt.c150
-rw-r--r--sos-code-article4/hwcore/gdt.h41
-rw-r--r--sos-code-article4/hwcore/i8254.c80
-rw-r--r--sos-code-article4/hwcore/i8254.h36
-rw-r--r--sos-code-article4/hwcore/i8259.c80
-rw-r--r--sos-code-article4/hwcore/i8259.h41
-rw-r--r--sos-code-article4/hwcore/idt.c160
-rw-r--r--sos-code-article4/hwcore/idt.h85
-rw-r--r--sos-code-article4/hwcore/ioports.h47
-rw-r--r--sos-code-article4/hwcore/irq.c91
-rw-r--r--sos-code-article4/hwcore/irq.h74
-rw-r--r--sos-code-article4/hwcore/irq_wrappers.S173
-rw-r--r--sos-code-article4/hwcore/paging.c455
-rw-r--r--sos-code-article4/hwcore/paging.h120
-rw-r--r--sos-code-article4/hwcore/segment.h59
-rw-r--r--sos-code-article4/sos/assert.h42
-rw-r--r--sos-code-article4/sos/errno.h40
-rw-r--r--sos-code-article4/sos/klibc.c271
-rw-r--r--sos-code-article4/sos/klibc.h84
-rw-r--r--sos-code-article4/sos/list.h186
-rw-r--r--sos-code-article4/sos/macros.h37
-rw-r--r--sos-code-article4/sos/main.c298
-rw-r--r--sos-code-article4/sos/physmem.c269
-rw-r--r--sos-code-article4/sos/physmem.h119
-rw-r--r--sos-code-article4/sos/types.h50
-rwxr-xr-xsos-code-article4/support/build_image.sh215
-rw-r--r--sos-code-article4/support/sos.lds107
178 files changed, 17952 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2aa725e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.o
+*.tgz
+*.iso
+*.img
diff --git a/sos-code-article1/INSTALL b/sos-code-article1/INSTALL
new file mode 100644
index 0000000..7c7d619
--- /dev/null
+++ b/sos-code-article1/INSTALL
@@ -0,0 +1,118 @@
+
+ SOS: A Simple Operating System
+
+ Compilation/Installation/Test instructions
+
+
+Compilation
+===========
+
+IMPORTANT
+---------
+
+Don't forget to run 'make clean' before 'make' after you have modified
+any source or header file(s).
+
+
+On a x86 host where grub is correctly installed
+-----------------------------------------------
+
+Simply run 'make'
+
+
+On a non-x86 host (without grub of course !)
+--------------------------------------------
+
+See extra/README
+
+
+On an x86 host without Grub, or with a buggy Grub
+-------------------------------------------------
+
+See extra/README
+
+How do I know I have a buggy grub installation ? Answer: in the qemu
+PC emulator, Grub hangs while loading the kernel
+
+
+Installation
+============
+
+Nothing special to do besides compiling
+
+
+Test the SOS Kernel
+===================
+
+On a x86 real machine with Grub installed
+-----------------------------------------
+
+ 1st method
+ => Boot the sos.elf file (append 'kernel=<path_to>sos.elf' in the
+ menu.lst or type it on Grub's command line) from a hard disk, a
+ floppy, or from the network
+
+ 2nd method
+ => Copy the file 'fd.img' to a floppy and boot from it
+
+
+On a x86 real machine without Grub installed
+--------------------------------------------
+
+ 1st method
+ => see extra/README to compile with the grub floppy image we provide,
+ copy the file 'fd.img' to a floppy, and boot from it
+
+ 2nd method
+ => see extra/README to compile with the boot sector we provide (up to
+ article 2 only), copy the file 'extra/sos_bsect.img' to a floppy,
+ and boot from it
+
+
+Inside a PC emulator (x86 and non-x86 hosts)
+--------------------------------------------
+
+Tested on both the bochs emulator (x86/linux, sparc/solaris and
+ppc/linux hosts, 'apt-get install bochs-x vgabios' on debian
+testing/unstable), and the qemu system emulator (with libsdl
+installed: 'apt-get install libsdl1.2-dev' on debian
+testing/unstable).
+
+ 1/ Grub is installed on the host (x86 hosts only)
+ - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ bochs: boot from the file 'fd.img'. Example of a ~/.bochsrc:
+ floppya: 1_44=/home/d2/sos/fd.img, status=inserted
+ romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
+ vgaromimage: /usr/share/vgabios/vgabios.bin
+ megs:63 # 63 Mo de RAM
+
+ qemu: run 'qemu -fda fd.img'
+ If grub hangs while loading the kernel, please go to method 2/
+
+ 2/ Grub is not installed (all hosts)
+ - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the Grub floppy
+ image we provide, and:
+
+ bochs: boot from the file 'fd.img'
+
+ qemu: run 'qemu -fda fd.img'
+
+ 3/ Bonus: boot with the bootsector we provide (all hosts, up to art. 2 ONLY !)
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the boot sector we
+ provide, and:
+
+ bochs: boot from the file 'extra/sos_bsect.img'
+
+ qemu: run 'qemu -fda extra/sos_qemu.img'
+
+ NOTE: After article 2, this way of booting is not supported: please
+ use the method 2/ above.
+
+
+--
+David Decotigny
diff --git a/sos-code-article1/LICENSE b/sos-code-article1/LICENSE
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/sos-code-article1/LICENSE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/sos-code-article1/Makefile b/sos-code-article1/Makefile
new file mode 100644
index 0000000..a0c82b2
--- /dev/null
+++ b/sos-code-article1/Makefile
@@ -0,0 +1,52 @@
+CC=i586-elf-gcc
+LD=i586-elf-ld
+CFLAGS = -Wall -nostdlib -nostdinc -ffreestanding -DKERNEL_SOS
+LDFLAGS = --warn-common
+OBJECTS = bootstrap/multiboot.o \
+ drivers/x86_videomem.o drivers/bochs.o \
+ sos/klibc.o sos/main.o
+
+KERNEL_OBJ = sos.elf
+MULTIBOOT_IMAGE = cdrom.iso
+PWD := $(shell pwd)
+
+# Main target
+all: $(MULTIBOOT_IMAGE)
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ)
+ # ./support/build_image.sh $@ $<
+ if [ ! -e cdrom/boot/grub/stage2_eltorito ]; then \
+ echo "Please copy grub's stage2_eltorito to cdrom/boot/grub."; \
+ exit -1; \
+ fi
+ cp $(KERNEL_OBJ) cdrom
+ echo timeout 0 > cdrom/boot/grub/menu.lst
+ echo title Simple OS >> cdrom/boot/grub/menu.lst
+ echo kernel /$(KERNEL_OBJ) >> cdrom/boot/grub/menu.lst
+ genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 \
+ -boot-info-table -input-charset ascii -A SOS -o $(MULTIBOOT_IMAGE) cdrom
+
+$(KERNEL_OBJ): $(OBJECTS)
+ $(LD) $(LDFLAGS) -T ./support/sos.lds -o $@ $^
+ -nm -C $@ | cut -d ' ' -f 1,3 > sos.map
+
+-include .mkvars
+
+# Create objects from C source code
+%.o: %.c
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -o $@
+
+# Create objects from assembler (.S) source code
+%.o: %.S
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -DASM_SOURCE=1 -o $@
+
+# Clean directory
+clean:
+ $(RM) *.iso *.img *.o mtoolsrc *~ menu.txt *.img *.elf *.bin *.map
+ $(RM) *.log *.out bochs*
+ $(RM) bootstrap/*.o bootstrap/*~
+ $(RM) drivers/*.o drivers/*~
+ $(RM) hwcore/*.o hwcore/*~
+ $(RM) sos/*.o sos/*~
+ $(RM) support/*~
+ $(RM) extra/*~
diff --git a/sos-code-article1/README b/sos-code-article1/README
new file mode 100644
index 0000000..efbbc89
--- /dev/null
+++ b/sos-code-article1/README
@@ -0,0 +1,90 @@
+
+ SOS: A Simple Operating System
+
+
+This is SOS, a Simple Operating System for i386-family
+processors. This is as simple as possible to show a way to program a
+basic Operating System on real common hardware (PC). The code should
+be easily readable and understandable thanks to frequent comments, and
+references to external documentation. We chose to implement the basic
+features of an OS, thus making design decisions targetting towards
+simplicity of understanding, covering most of the OS classical
+concepts, but not aiming at proposing yet another full-fledged
+competitive OS (Linux is quite good at it). However, for those who
+would like to propose some enhancements, we are open to any code
+suggestions (patches only, please). And yes, there might be bugs in
+the code, so please send us any bug report, and/or patches !
+
+The OS comes as a set of articles (in french) to be published in the
+journal "Linux Magazine France". Each month, the part of the code
+related to the current article's theme is released (see VERSION file),
+and the resulting OS can be successfully compiled and run, by booting
+it from a floppy on a real machine (tested AMD k7, Cyrix and Intel P4
+pentiums), or through an x86 emulator (bochs or qemu). The resulting
+OS is available as a multiboot compliant ELF kernel (sos.elf) and as a
+floppy image (fd.img). It provides a very very very basic demo whose
+aim is to understand how everything works, not to animate sprites on
+the screen with 5:1 dolby sound.
+
+The initial technical features and lack-of-features of the OS are:
+ - monolithic kernel, fully interruptible, non-preemptible (big kernel
+ lock), target machines = i386 PC or better
+ - compiles on any host where the gcc/binutils toolchain (target
+ i586-gnu) is available. Can be tested on real i486/pentium
+ hardware, or on any host that can run an i486/pentium PC emulator
+ (bochs or qemu)
+ - kernel loaded by grub, or by a sample bootsector (up to article 2
+ ONLY)
+ - clear separation of physical memory and virtual memory concepts,
+ even inside the kernel: no identity-mapping of the physical memory
+ inside the kernel (allows to move virtual mappings of kernel pages
+ at run-time, eg to free ISA DMA pages, and to avercome the 4G RAM
+ barrier)
+ - slab-type kernel memory allocation
+ - no swap, no reverse mapping
+ - VERY simple drivers: keyboard, x86 video memory, IDE disks
+ - logical devices: partitions, FAT filesystem, "hard-coded"
+ mountpoints only (~ MSDOS)
+ - no network stack
+ - user-level features: ELF loader (no shared libraries), processes,
+ user threads (kernel-level scheduling only), mmap API, basic VFS
+
+To understand where to look at for what, here is a brief description:
+ - Makefile: the (ONLY) makefile of the OS. Targets are basically
+ 'all' and 'clean'
+ - bootstrap/ directory: code to load the kernel. Both the stuff
+ needed for a multiboot-compliant loader (eg grub) AND a bootsector
+ are provided. The bootsector may only be used up to article 2.
+ - sos/ directory: the entry routine for the kernel (main.c), various
+ systemwide header files, a set of common useful C routines
+ ("nano-klibc"), and kernel subsystems (kernel memory management,
+ etc...)
+ - hwcore/ directory: Low-level CPU- and kernel-related routines
+ (interrupt/exception management, translation tables and segment
+ registers, ...)
+ - drivers/ directory: basic kernel drivers for various (non CPU)
+ devices (keyboard, x86 video memory, bochs 0xe9 port, ...). Used
+ mainly for debugging
+ - support/ directory: scripts and configuration files to build the
+ floppy images
+ - extra/ directory: a set of configuration files to be customized for
+ non-x86 host installations (yes, we primarily develop SOS on a ppc, for
+ the x86 target of course), or for grub-less installations. See
+ README file in this directory.
+
+The code is licensed under the terms of the GNU GPL version 2 (see
+LICENSE file).
+
+Enjoy !
+
+ David Decotigny, Thomas Petazzoni, the Kos team
+ http://sos.enix.org/
+ http://david.decotigny.free.fr/
+ http://kos.enix.org/~thomas/
+ http://kos.enix.org/
+
+
+--
+David Decotigny
+
+PS: Made with a Mac.
diff --git a/sos-code-article1/VERSION b/sos-code-article1/VERSION
new file mode 100644
index 0000000..bb070ec
--- /dev/null
+++ b/sos-code-article1/VERSION
@@ -0,0 +1,11 @@
+SOS -- Simple OS
+Copyright (C) 2003,2004 The SOS Team (David Decotigny & Thomas Petazzoni)
+
+Version "Article 1" -- Booting
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See the LICENSE file included in the distribution.
diff --git a/sos-code-article1/bootstrap/multiboot.S b/sos-code-article1/bootstrap/multiboot.S
new file mode 100644
index 0000000..4a7c65b
--- /dev/null
+++ b/sos-code-article1/bootstrap/multiboot.S
@@ -0,0 +1,74 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+
+/* The operating system is booted by Grub, so we almost have nothing
+ to do to boot it. We only have to conform to the Multiboot
+ standard, as defined by the Grub documentation */
+
+#define ASM 1
+/* The multiboot.h header contains a lot of multiboot standard
+ definitions */
+#include "multiboot.h"
+
+ /* The multiboot header itself. It must come first. */
+.section ".multiboot"
+ /* Multiboot header must be aligned on a 4-byte boundary */
+ .align 4
+multiboot_header:
+ /* magic= */ .long MULTIBOOT_HEADER_MAGIC
+ /* flags= */ .long MULTIBOOT_HEADER_FLAGS
+ /* checksum= */ .long -(MULTIBOOT_HEADER_MAGIC \
+ +MULTIBOOT_HEADER_FLAGS)
+ /* header_addr= */ .long multiboot_header
+ /* load_addr= */ .long __b_kernel
+ /* load_end_addr=*/ .long __e_load
+ /* bss_end_addr= */ .long __e_kernel
+ /* entry_addr= */ .long multiboot_entry
+
+/* Here is the beginning of the code of our operating system */
+.text
+
+.globl start, _start
+start:
+_start:
+multiboot_entry:
+ /* Set up a stack */
+ movl $(stack + MULTIBOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Set EFLAGS to 0 */
+ pushl $0
+ /* pop stack into the EFLAGS register */
+ popf
+
+ /* Push the magic and the address on the stack, so that they
+ will be the parameters of the cmain function */
+ pushl %ebx
+ pushl %eax
+
+ /* Call the cmain function (os.c) */
+ call EXT_C(sos_main)
+
+ /* Should never get there */
+loop:
+ hlt
+ jmp loop
+
+ /* Here is the stack */
+.comm stack, MULTIBOOT_STACK_SIZE
diff --git a/sos-code-article1/bootstrap/multiboot.h b/sos-code-article1/bootstrap/multiboot.h
new file mode 100644
index 0000000..bee676d
--- /dev/null
+++ b/sos-code-article1/bootstrap/multiboot.h
@@ -0,0 +1,129 @@
+#ifndef __MULTIBOOT_H__
+#define __MULTIBOOT_H__
+
+/* multiboot.h - the header for Multiboot */
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Macros. */
+
+/* The magic number for the Multiboot header. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* The flags for the Multiboot header. */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* The magic number passed by a Multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (16KB). */
+#define MULTIBOOT_STACK_SIZE 0x4000
+
+#define MULTIBOOT_CMDLINE 4
+#define MULTIBOOT_MODS 8
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* Do not include here in boot.S. */
+
+
+
+/* Types. */
+
+/* The Multiboot header. */
+typedef struct multiboot_header
+{
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* The symbol table for a.out. */
+typedef struct aout_symbol_table
+{
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* The section header table for ELF. */
+typedef struct elf_section_header_table
+{
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* The Multiboot information. */
+typedef struct multiboot_info
+{
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union
+ {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+ unsigned long drives_length;
+ unsigned long drives_addr;
+} multiboot_info_t;
+
+/* The module structure. */
+typedef struct module
+{
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* The memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map
+{
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+void dump_multiboot_info(multiboot_info_t *mbi);
+
+#endif /* ! ASM */
+
+#endif /* __MULTIBOOT_H__ */
diff --git a/sos-code-article1/cdrom/boot/grub/menu.lst b/sos-code-article1/cdrom/boot/grub/menu.lst
new file mode 100644
index 0000000..351100d
--- /dev/null
+++ b/sos-code-article1/cdrom/boot/grub/menu.lst
@@ -0,0 +1,3 @@
+timeout 0
+title Simple OS
+kernel /sos.elf
diff --git a/sos-code-article1/cdrom/boot/grub/stage2_eltorito b/sos-code-article1/cdrom/boot/grub/stage2_eltorito
new file mode 100644
index 0000000..6d82f08
--- /dev/null
+++ b/sos-code-article1/cdrom/boot/grub/stage2_eltorito
Binary files differ
diff --git a/sos-code-article1/cdrom/sos.elf b/sos-code-article1/cdrom/sos.elf
new file mode 100755
index 0000000..9dcfd43
--- /dev/null
+++ b/sos-code-article1/cdrom/sos.elf
Binary files differ
diff --git a/sos-code-article1/drivers/bochs.c b/sos-code-article1/drivers/bochs.c
new file mode 100644
index 0000000..db18599
--- /dev/null
+++ b/sos-code-article1/drivers/bochs.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <hwcore/ioports.h>
+#include <sos/klibc.h>
+
+#include "bochs.h"
+
+/* This is a special hack that is only useful when running the
+ operating system under the Bochs emulator. */
+#define SOS_BOCHS_IOPORT 0xe9
+
+sos_ret_t sos_bochs_setup(void)
+{
+ return SOS_OK;
+}
+
+
+#define sos_bochs_putchar(chr) \
+ outb((chr), SOS_BOCHS_IOPORT)
+
+sos_ret_t sos_bochs_putstring(const char* str)
+{
+ for ( ; str && (*str != '\0') ; str++)
+ sos_bochs_putchar(*str);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes)
+{
+ unsigned c;
+
+#define BOCHS_PRTHEX(q) \
+ ({ unsigned char r; if ((q) >= 10) r='a'+(q)-10; \
+ else r='0'+(q); sos_bochs_putchar(r); })
+
+ switch (nbytes)
+ {
+ case 4:
+ c = (val >> 24) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 3:
+ c = (val >> 16) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 2:
+ c = (val >> 8) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 1:
+ c = val & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes)
+{
+ int offs;
+ for (offs = 0 ; offs < nbytes ; offs++)
+ {
+ const unsigned char *c;
+
+ if ((offs % 16) == 0)
+ {
+ sos_bochs_putstring("0x");
+ sos_bochs_puthex(offs, 4);
+ }
+
+ if ((offs % 8) == 0)
+ sos_bochs_putstring(" ");
+
+ c = (const unsigned char*)(addr + offs);
+ sos_bochs_puthex(*c, 1);
+ sos_bochs_putstring(" ");
+
+ if (((offs + 1) % 16) == 0)
+ sos_bochs_putstring("\n");
+ }
+
+ if (offs % 16)
+ sos_bochs_putstring("\n");
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_bochs_putstring(buff);
+}
diff --git a/sos-code-article1/drivers/bochs.h b/sos-code-article1/drivers/bochs.h
new file mode 100644
index 0000000..310b023
--- /dev/null
+++ b/sos-code-article1/drivers/bochs.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_BOCHS_H_
+#define _SOS_BOCHS_H_
+
+/**
+ * @file bochs.h
+ *
+ * If you compiled Bochs with the --enable-e9-hack, then any character
+ * printed to the 0xE9 I/O port is printed to the xterm that is
+ * running Bochs. This may appear to be a detail, but in fact, this
+ * functionnality is *VERY* precious for debugging purposes. This
+ * """driver""" handles this feature.
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+
+sos_ret_t sos_bochs_setup(void);
+
+sos_ret_t sos_bochs_putstring(const char* str);
+
+/** Print the least signficant 32 (nbytes == 4), 24 (nbytes == 3), 16
+ (nbytes == 2) or 8 (nbytes == 1) bits of val in hexadecimal. */
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes);
+
+/** hexdump-style pretty printing */
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#endif
diff --git a/sos-code-article1/drivers/x86_videomem.c b/sos-code-article1/drivers/x86_videomem.c
new file mode 100644
index 0000000..cc4b79c
--- /dev/null
+++ b/sos-code-article1/drivers/x86_videomem.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <sos/klibc.h>
+#include <hwcore/ioports.h>
+
+#include "x86_videomem.h"
+
+/* The text video memory starts at address 0xB8000. Odd bytes are the
+ ASCII value of the character, even bytes are attribute for the
+ preceding character. */
+#define VIDEO 0xb8000
+
+
+/* Console screen size */
+#define LINES 25
+#define COLUMNS 80
+
+
+/** The structure of a character element in the video memory. @see
+ http://webster.cs.ucr.edu/AoA DOS edition chapter 23 */
+typedef struct {
+ unsigned char character;
+ unsigned char attribute;
+} __attribute__ ((packed)) x86_video_mem[LINES*COLUMNS];
+
+
+
+/** The base pointer for the video memory */
+static volatile x86_video_mem *video = (volatile x86_video_mem*)VIDEO;
+
+sos_ret_t sos_x86_videomem_setup(void)
+{
+ /*
+ * Hide cursor. @see Ralf Brown's interrupt (and port) list
+ * http://www-2.cs.cmu.edu/~ralf/files.html
+ */
+#define CRT_REG_INDEX 0x3d4
+#define CRT_REG_DATA 0x3d5
+
+ /* CRT index port => ask for access to register 0xa ("cursor
+ start") */
+ outb(0x0a, CRT_REG_INDEX);
+
+ /* (RBIL Tables 708 & 654) CRT Register 0xa => bit 5 = cursor OFF */
+ outb(1 << 5, CRT_REG_DATA);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute)
+{
+ /* Clears the screen */
+ int i;
+ for(i = 0 ; i < LINES*COLUMNS ; i++)
+ {
+ (*video)[i].character = 0;
+ (*video)[i].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ for ( ; str && *str && (video_offs < LINES*COLUMNS) ; str++, video_offs++)
+ {
+ (*video)[video_offs].character = (unsigned char)*str;
+ (*video)[video_offs].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ (*video)[video_offs].character = c;
+ (*video)[video_offs].attribute = attribute;
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_x86_videomem_putstring(row, col, attribute, buff);
+}
diff --git a/sos-code-article1/drivers/x86_videomem.h b/sos-code-article1/drivers/x86_videomem.h
new file mode 100644
index 0000000..31a9dfc
--- /dev/null
+++ b/sos-code-article1/drivers/x86_videomem.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_X86_VIDEOMEM_H_
+#define _SOS_X86_VIDEOMEM_H_
+
+/**
+ * @file x86_videomem.h
+ *
+ * On x86 PC platforms, the text mode screen memory (and CGA/EGA/VGA
+ * too) is mapped into physical memory. This file handles access to
+ * this screen, supposed to be set in text-mode, through this memory
+ * area. All the functions below print the characters directly to the
+ * memory, without interpreting the escaped characters (such as \n,
+ * \r...)
+ */
+
+#include <sos/errno.h>
+
+/**
+ * x86 video attributes
+ * See http://webster.cs.ucr.edu/AoA/DOS/ch23/CH23-1.html
+ */
+/* Normal and Dark/Light foreground */
+#define SOS_X86_VIDEO_FG_BLACK 0
+#define SOS_X86_VIDEO_FG_DKGRAY 8
+#define SOS_X86_VIDEO_FG_BLUE 1
+#define SOS_X86_VIDEO_FG_LTBLUE 9
+#define SOS_X86_VIDEO_FG_GREEN 2
+#define SOS_X86_VIDEO_FG_LTGREEN 10
+#define SOS_X86_VIDEO_FG_CYAN 3
+#define SOS_X86_VIDEO_FG_LTCYAN 11
+#define SOS_X86_VIDEO_FG_RED 4
+#define SOS_X86_VIDEO_FG_LTRED 12
+#define SOS_X86_VIDEO_FG_MAGENTA 5
+#define SOS_X86_VIDEO_FG_LTMAGENTA 13
+#define SOS_X86_VIDEO_FG_BROWN 6
+#define SOS_X86_VIDEO_FG_YELLOW 14
+#define SOS_X86_VIDEO_FG_LTGRAY 7
+#define SOS_X86_VIDEO_FG_WHITE 15
+/* Background */
+#define SOS_X86_VIDEO_BG_BLACK (0 << 4)
+#define SOS_X86_VIDEO_BG_BLUE (1 << 4)
+#define SOS_X86_VIDEO_BG_GREEN (2 << 4)
+#define SOS_X86_VIDEO_BG_CYAN (3 << 4)
+#define SOS_X86_VIDEO_BG_RED (4 << 4)
+#define SOS_X86_VIDEO_BG_MAGENTA (5 << 4)
+#define SOS_X86_VIDEO_BG_BROWN (6 << 4)
+#define SOS_X86_VIDEO_BG_LTGRAY (7 << 4)
+/* Blinking */
+#define SOS_X86_VIDEO_FG_BLINKING (1 << 7)
+
+
+/** Setup the video RAM mapping and clear the screen */
+sos_ret_t sos_x86_videomem_setup(void);
+
+/** Clears the screen and set the background color as given by
+ attribute */
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute);
+
+/** Print the string on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str);
+
+/** Print the character on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+ __attribute__ ((format (printf, 4, 5)));
+
+#endif /* _SOS_X86_VIDEOMEM_H_ */
diff --git a/sos-code-article1/extra/Makefile b/sos-code-article1/extra/Makefile
new file mode 100644
index 0000000..f858aa6
--- /dev/null
+++ b/sos-code-article1/extra/Makefile
@@ -0,0 +1,40 @@
+OBJCOPY=objcopy
+
+all: sos_qemu.img
+
+-include ../.mkvars
+
+# The image is the simple concatenation of the boot sector and the kernel
+# It may be use in bochs or on a real floppy, but NOT in qemu (see below)
+sos_bsect.img: bsect.bin sos.bin
+ cat $^ > $@
+ @echo "You can use the $@ image in bochs or on a real floppy (NOT qemu)"
+
+# For qemu, the trick is to tell it we have *more* than 1440 sectors (720kB).
+# Rtherwise the qemu disk geometry will be configured to be that of a 720kB
+# floppy, while our boot sector assumes it to be 1.44MB
+sos_qemu.img: sos_bsect.img
+ # Padding with 0s after the bsect/kernel image
+ cat $< /dev/zero | dd of=$@ bs=1k count=1440
+ @echo "You can use the $@ image in qemu, bochs, or on a real floppy"
+
+# we extract the boot sector from the main ELF binary
+bsect.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -j .bootsect $< $@
+
+# we extract the kernel code from the main ELF binary
+sos.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -R .bootsect $< $@
+
+# The main ELF binary contains the boot sector and the kernel code
+# linked together (hence we deal with a SINGLE image that we split
+# above) because they share some symbol definitions
+sos_bsect.elf: bootsect.o compile_kernel
+ $(LD) --warn-common -T ./sos_bsect.lds -o $@ \
+ bootsect.o $(wildcard ../hwcore/*.o ../drivers/*.o ../sos/*.o)
+
+compile_kernel:
+ $(MAKE) -C ..
+
+clean:
+ $(RM) *.img *.elf *.bin *~ *.o *.out
diff --git a/sos-code-article1/extra/README b/sos-code-article1/extra/README
new file mode 100644
index 0000000..0272f1f
--- /dev/null
+++ b/sos-code-article1/extra/README
@@ -0,0 +1,73 @@
+
+Contents of the extra/ directory
+================================
+
+Data and configuration files to support generation of sos on non-x86
+and/or grub-less hosts:
+ - dot.mkvars: file to copy as .mkvars in the root directory to
+ compile on a non-x86 host, and to generate the grub floppy image on
+ a grub-less host
+ - grub.img.gz: compressed image of a Grub floppy (without any
+ kernel). Used by dot.mkvars.
+ - mtoolsrc: file needed by .mkvars to compile a the floppy image
+
+Support of a sos-specific boot sector:
+ - Makefile: rules to compile sos_bsect.img, the floppy image with the
+ boot sector and the Sos
+ - bootsect.S: x86 Sos boot sector (GNU as). Depends on sos_bsect.lds
+ - sos_bsect.lds: ld script to bind the boot sector with the remaining
+ of the kernel
+
+Misc:
+ - qemu-port-e9.diff: patch over qemu to support the bochs "port 0xe9 hack"
+
+
+What you can do with these files
+================================
+
+
+*** Compile SOS from another architecture:
+------------------------------------------
+ - compile a cross-compiler for the i586-gnu target. This involves
+ compiling the binutils and gcc. Here are example configuration
+ options for them:
+ binutils (replace sparc-cun-solaris with your arch):
+ ../binutils-2.13/configure --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/binutils-2.11 --host=sparc-sun-solaris2.7 i586-gnu
+ make && make install
+ gcc (ditto):
+ CFLAGS="-O2 -Dinhibit_libc" ../gcc-3.2/configure --target=i586-gnu --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/gcc-3.2 --with-as=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/as --with-ld=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/ld --with-gnu-as --with-gnu-ld --enable-languages=c --disable-shared --disable-multilib --disable-nls --enable-threads=single
+ make && make install
+ - compile the mtools
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS from an x86 where grub is not or incorrectly installed:
+--------------------------------------------------------------------------
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS with its own bootloader:
+-------------------------------------------
+ - for cross-architecture compilation: see above
+ - cd to this extra/ directory
+ - run 'make'
+ - the floppy image is: sos_bsect.img
+ NOTE : SOS will not boot correctly this way after article 2 !
+
+
+--
+David Decotigny
diff --git a/sos-code-article1/extra/bootsect.S b/sos-code-article1/extra/bootsect.S
new file mode 100644
index 0000000..f01ca20
--- /dev/null
+++ b/sos-code-article1/extra/bootsect.S
@@ -0,0 +1,393 @@
+
+/*
+ * @(#) $Id: bootsect.S,v 1.6 2004/06/18 07:43:51 d2 Exp $
+ * Description : Bootsecteur en syntaxe AT&T
+ * Auteurs : Thomas Petazzoni & Fabrice Gautier & Emmanuel Marty
+ * Jerome Petazzoni & Bernard Cassagne & coffeeman
+ * David Decotigny
+ * Bug reports to kos-misc@enix.org
+ */
+
+/*
+ * But global de ce bootsecteur :
+ *
+ * - Initialiser la becane
+ * - Charger le kernel
+ * - Passer en mode protege
+ * - Executer le kernel
+ *
+ * Taille restante : Je vous rappelle qu'un bootsecteur ne peut faire
+ * qu'au maximum 512 octets dont 2 octets obligatoires 0xAA55. Sur
+ * les 510 octets reellement utilisables, il reste 3 octets dispo (60
+ * si on decide d'enlever le BPB un jour) !!!
+ *
+ * thomas_petazzoni : - detection des codes d'erreurs de chargement
+ * David_Decotigny : - Passage en GNU as
+ * David_Decotigny : - Chargement du noyau au-dela du 1er Mega (taille
+ * max = 0x9e000 octets = 632ko), pour avoir le
+ * meme noyau sous grub et avec le bootsecteur
+ */
+
+ /*
+ * Sequence d'operations :
+ * - Le BIOS charge le bootsect en 0x7c00 (BOOT_ADRESS). On choisit
+ * la representation 0x7c0:0000 pour que le .org 0 reste valide
+ * - Le bootsect se deplace de lui-meme en 0x9f000 (COPY_ADRESS). On
+ * choisit la representation 0x9f00:0000 pour que le .org 0 reste
+ * valide
+ * - Le bootsect verifie que le processeur est du type 386+
+ * - Il charge le noyau depuis la disquette en memoire a partir de
+ * 0x1000 (LOAD_ADRESS). Le noyau peut au max tenir sur
+ * SECTORS_TO_LOAD secteurs
+ * - Il passe en pmode flat (apres ouverture a20)
+ * - Il recopie le noyau (situe en LOAD_ADRESS) vers son adresse
+ * finale (FINAL_ADDRESS = 2Mo). La recopie se fait sur tout l'espace
+ * LOAD_ADRESS ---> COPY_ADRESS, c'est a dire sur 0x9e000 octets =
+ * 632ko. Le noyau peut donc au max faire 632ko. Le nombre max de
+ * secteurs de disquette qu'on peut charger est donc 1264
+ */
+
+
+/* La taille de la pile */
+#define BOOT_STACK_SIZE 0x4000
+
+ .file "bootsect.S"
+
+ /* Tout est place dans une seule section */
+ .section ".bootsect"
+
+ /* L'essentiel du bootsector (sauf les 1eres instructions)
+ sont a un offset 0. On fait en sorte que le compilo soit
+ d'accord la-dessus. Quand on a des adresse realm exotiques
+ (0x7c00, 0x9f000, ...), on s'arrange toujours pour avoir un
+ offset de 0 => on choisira le segment adapte (0x7c0,
+ 0x9f00, ...). Il ne faut pas oublier le ld -Ttext 0 */
+ .org 0
+
+ /* Pour que gas genere du 16bits, afin que ca marche en realm */
+ .code16
+
+#define SECTORS_TO_LOAD 128 /* 64 ko */ /* MAX=1264 */
+
+/*
+ * Parametres de la disquette. Comme c'est chiant de faire une
+ * procedure de detection auto, et que ca prend de la place, on fait
+ * ca "a la main". Par exemple, une DD 720 Ko a 9 secteurs/piste, une
+ * 1.44 Mo a 18 secteurs/pistes
+ */
+#define CYLS 80
+#define HEADS 1
+#define SECTS 18
+
+#define BOOT_ADRESS 0x07C00 /* Adresse de demarrage (lineaire) */
+#define BOOT_SEG (BOOT_ADRESS>>4) /* Segment de Boot */
+#define BOOT_SIZE 512 /* Taille bu bootsecteur */
+#define COPY_ADRESS 0x9F000 /* La ou on va copier le
+ bootsecteur (lineaire) */
+#define COPY_SEG (COPY_ADRESS>>4) /* Segment de la ou on va
+ copier le bootsecteur */
+#define LOAD_ADRESS 0x01000 /* 1er chargement du systeme */
+#define LOAD_SEG (LOAD_ADRESS>>4) /* Segment du 1er chargement du */
+#define MAX_KERN_LEN COPY_ADRESS-LOAD_ADRESS /* Taille noyau maxi */
+
+/* IMPORTANT : Cette valeur DOIT etre identique a l'adresse presente
+ dans sos.lds ! */
+#define FINAL_ADDRESS 0x200000 /* Adresse finale (physique de 0 a 4G)
+ ou est charge le noyau */
+
+#define OP16 .byte 0x66 ;
+#define OP32 .byte 0x66 ;
+
+/*
+ * Procedure qui vide le buffer clavier.
+ */
+#define WAITKB \
+ 1: ;\
+ .word 0xeb ;\
+ .word 0xeb ;\
+ inb $0x64, %al ;\
+ andb $0x2, %al ;\
+ jnz 1b
+
+ /* Le point d'entree dans le bootsect */
+.globl _bsect
+_bsect:
+
+ /*
+ * La portion qui suit est situee a un offset 0x7c00 en
+ * memoire. Attention donc aux references memoire dans cette
+ * partie. On choisit de rester en offset 0 (.org 0), mais on
+ * charge correctement les segments a 0x7c0.
+ */
+
+ movw $BOOT_SEG, %ax /* le bootsecteur est a 0x7C00 en lineaire */
+ movw %ax, %ds /* on le copie a l'adresse COPY_ADRESS */
+ xorw %si, %si /* comme cette adresse est la plus haute de la mem */
+ xorw %di, %di /* on pourra charger un kernel + gros */
+ movw $(BOOT_SIZE>>1), %cx
+ movw $COPY_SEG, %ax
+ movw %ax, %es
+ cld
+ rep ; movsw
+
+ /* on continue a executer le bootsecteur, mais maintenant a
+ partir de 0x9F000, qu'on represente sous la forme
+ 0x9f00:offset */
+ ljmp $COPY_SEG, $here
+
+ /*
+ * A partir de maintenant, on est a un offset 0 en memoire
+ * (segment 0x9f00), conformement a ce que veut le compilo.
+ */
+here:
+ movw %ax, %ds
+
+ /* Petite pile temporaire (1k - 3.84k en RAM ; les adresses 0-1k
+ correspondent au vecteur d'interruptions). */
+ movw %ax, %ss
+ movw $(LOAD_ADRESS - 0x10), %sp
+
+ /* Efface l'ecran */
+ movb $0x0, %ah
+ movb $0x3, %al
+ int $0x10
+
+ /* Affiche les messages d'attente */
+ movw $loadkern, %si
+ call message
+ movw $check, %si
+ call message
+
+check386:
+ /*
+ * la attention, plus complexe : on teste si le proc est un
+ * 386+ pour cela, on va essayer de modifier les bits 12 ? 14
+ * du registre E-flag si la modification reste, alors le proc
+ * est un 386+, sinon, c'est =< 286
+ *
+ * Merci a Emmanuel Marty pour la compatibilite avec les 386
+ * "pre-jurassique"
+ */
+
+ pushf /* on sauvegarde le E-Flag */
+ movb $0x70, %ah
+ pushw %ax
+ popf
+ pushf
+ popw %ax
+ orb %ah, %ah
+ je no386 /* si la modif n'est pas valable, alors on saute a
+ no386 */
+ popf /* on les restaure ? la fin ... */
+
+ /* Message de confirmation de 386+ et d'attente */
+ movw $found386, %si
+ call message
+ movw $loading, %si
+ call message
+
+/* Copie du noyau disquette => RAM a partir de 0x1000
+ L'adresse de destination est définie par es:0, où es vaut
+ initialement 0x100 (ie correspond alors à l'adresse 256*16, soit 4
+ ko). Chaque itération incrémente ce registre es de 32, ce qui
+ correspond à un bond de 32*16 en mémoire, soit la taille d'un
+ secteur. De cette façon, puisqu'on joue sur les segments plutôt que
+ sur les offsets, la taille du noyau n'est pas limitée à 64 ko. Elle
+ est limitée par contre à la taille de la mémoire disponible sous
+ les 1Mo, \ie 640 ko (0x9f000 - 0x1000). */
+copyKernel:
+ /* Chargement du noyau en LOAD_SEG:0 */
+ /* 3 iterateurs :
+ - load_size : le nbre de secteurs a charger
+ - cl : le secteur ou on en est pour le
+ cylindre en cours (<= SECTS)
+ - dh : la tete en cours (0/1)
+ */
+ movb $0, %dl
+ movw $LOAD_SEG, %ax
+ movw %ax, %es
+
+ xorw %bx, %bx
+ xorw %dx, %dx
+ movw $1, %cx /* premier secteur */
+
+.nextsector: /* prochain secteur */
+ incb %cl /* en incrementant CL */
+ cmpb $SECTS, %cl /* si CL =< SECTS (=nbre de secteurs/pistes)
+ alors on charge */
+ jbe .sector
+ movb $1, %cl /* sinon on revient au secteur 1 */
+ incb %dh /* mais sur l'autre tete */
+ cmpb $1, %dh /* on recompare, si DH =< 1 */
+ je .sector /* on charge */
+ movb $0, %dh /* sinon on repasse a la tete 0 */
+ incb %ch /* mais on change de cylindre */
+
+.sector:
+ pushw %es
+ movw $0x0201, %ax /* service 0x2, chargement 0x1 seecteur */
+ int $0x13 /* Go ! */
+ jc halt /* erreur */
+ popw %ax
+ addw $32, %ax /* on a charge un secteur, donc on doit
+ charger 512 bytes plus loin */
+ movw %ax, %es /* on avance donc le segment du buffer de
+ 32bytes, ie 1 secteur en RAM (car 32*16=512) */
+
+ movw $(0x0E*256+'.'), %ax /* affiche un point */
+ int $0x10
+
+ decw (load_size) /* et on repart pour le prochain secteur
+ tant qu'on n'a pas fini ! */
+ jnz .nextsector
+
+after:
+ movw $0x03f2, %dx
+ inb %dx, %al /* stoppe le moteur */
+ andb $0x0f, %al
+ outb %al, %dx
+
+ cli /* on interdit les interruptions */
+
+fincopie:
+ pushw %cs
+ popw %ds
+
+ /* on ouvre la porte A20 */
+ WAITKB /* on vide le buffer */
+ movb $0xd1, %al /* on met a jour le port */
+ outb %al, $0x64
+ WAITKB
+ movb $0xdf, %al /* bit 2 = ouverture/fermeture */
+ outb %al, $0x60
+
+ /*
+ * init gdt
+ */
+InitGDT:
+ /* Préparation du flat mode */
+ lgdt gdtr
+
+GoPMode:
+ /* Passage en mode protégé */
+ movl %cr0, %eax
+ orb $1, %al /* set PE bit to 1 */
+ movl %eax, %cr0
+
+ /* we are not yet in Pmode jump 'in' pmode clearing prefetch
+ * queue and loading a new selector */
+ movw $0x10, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+/*
+ * Code 32 bits ============================================================
+ */
+ .code32
+
+JumpToHere32: /* Se deplace a l'endroit actuel, en passant en 32bits
+ et en utilisant la gdt, et vide la prefetch queue */
+ .byte 0x66 /* Prefixe 32bits : en realite, jusqu'au jmp, on est
+ encore en 16 bits */
+ ljmp $0x8, $(COPY_ADRESS+(Here32))
+Here32:
+ /* Et voila : On est en 32 bits vrai */
+
+MoveKernelToFinalAddr: /* Deplace le noyau (en LOAD_ADDRESS) vers sa
+ destination finale (FINAL_ADDRESS) */
+ movl $0x10, %eax
+ movl %eax, %ds /* Seg Src = DSeg */
+ movl %eax, %es /* Sed Dest = DSeg */
+ cld
+ movl $LOAD_ADRESS, %esi /* On commence la copie au debut du noyau */
+ movl $FINAL_ADDRESS, %edi /* On copie vers cette adresse */
+ movl $MAX_KERN_LEN, %ecx /* Taille recopie */
+ shrl $2, %ecx
+ rep
+ movsl
+
+LaunchKernel:
+ /* Met en place une pile au niveau du symbole "stack" */
+ movl %eax, %ss
+ movl $(stack + BOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Saut vers le noyau. La GDT est en place (flat mode), les
+ * selecteurs aussi, a20 est ouverte, et les interruptions sont
+ * cli + pas de idt. Le PIC n'est pas programme */
+ ljmp $0x8, $sos_main
+
+/*
+ * Utilities ============================================================
+ */
+ .code16
+
+message:
+ lodsb /* charge ds:si dans al et incremente si */
+ orb %al, %al /* si al = 0 */
+ jz 1f
+ movb $0x0e, %ah /* service 0Eh (affichage d'un caractere) */
+ movw $0x0007, %bx /* Parametres : blanc sur fond noir */
+ int $0x10 /* Appel de l'interruption 10h */
+ jmp message /* On repart au début ... */
+ 1: ret /* si la chaine est finie alors on retourne
+ dans la fonction appelante */
+
+halt:
+ pushw %cs
+ popw %es
+ movw $haltmsg, %si
+ call message
+ cli
+ 1: jmp 1b
+ ret
+
+no386:
+ movw $need386, %si
+ call message
+ call halt
+
+ /*
+ * GDT
+ */
+
+gdt:
+gdtr:
+NULL_Desc:
+ .word (EndGDT)-(gdt)-1 /* Taille GDT */
+ .long (gdt)+COPY_ADRESS
+unused:
+ .word 0
+
+CS_Desc: /* 0x8 */
+ .word 0xFFFF, 0
+ .byte 0, 0x9B, 0xCF, 0
+
+DS_Desc: /* 0x10 */
+ .word 0xFFFF, 0
+ .byte 0, 0x93, 0xCF, 0
+
+EndGDT:
+
+ /* quelques messages */
+
+loadkern: .string "-= S O S =- : The Simple Operating System \r\n"
+check: .string "Checking for a 386+ processor... "
+found386: .string " [OK]\r\n"
+need386: .string " [FAILED]\r\n"
+diskerror: .string "Disk Error\r\n"
+loading: .string "Loading... "
+haltmsg: .string "System Halted\r\n"
+
+/*** Les code/données du boot secteur se terminent ICI. le marqueur de
+ * fin (aa55) est ajouté automatiquement par le script ld
+ * sos_bsect.lds ***/
+
+/* La pile de 16k qu'on utilise au niveau de LaunchKernel se trouve
+ declaree avec le noyau, dans sa section ".bss", cad HORS du boot
+ secteur ! (sinon ca depasserait 512B, forcément). On aurait pu la
+ définir directement dans le sos_bsect.lds, ou dans un fichier .c
+ auxiliaire pour plus de clarté */
+.comm stack, BOOT_STACK_SIZE
diff --git a/sos-code-article1/extra/dot.mkvars b/sos-code-article1/extra/dot.mkvars
new file mode 100644
index 0000000..1f7dca5
--- /dev/null
+++ b/sos-code-article1/extra/dot.mkvars
@@ -0,0 +1,29 @@
+# For cross-compilation and/or installations without grub available,
+# copy this file as .mkvars to the root directory of the SOS sources,
+# and customize the CC/LD/... variables. You still need the mtools
+# installed and running
+
+CC := i586-gnu-gcc
+LD := i586-gnu-ld
+OBJCOPY := i586-gnu-objcopy
+CFLAGS += -O3
+
+# Configuration of mtools
+MTOOLSRC = extra/mtoolsrc
+export MTOOLSRC
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ) menu.txt
+ gzip -dc < extra/grub.img.gz > $@
+ mcopy menu.txt v:/boot/grub/
+ mmd v:/system
+ mcopy sos.elf v:/system/sos.elf
+
+menu.txt:
+ echo timeout 0 > $@
+ echo default 0 >> $@
+ echo title SOS >> $@
+ echo "root (fd0)" >> $@
+ echo kernel /system/sos.elf >> $@
+
+runbochs: all
+ echo c | bochs -q
diff --git a/sos-code-article1/extra/grub.img.gz b/sos-code-article1/extra/grub.img.gz
new file mode 100644
index 0000000..4f98e74
--- /dev/null
+++ b/sos-code-article1/extra/grub.img.gz
Binary files differ
diff --git a/sos-code-article1/extra/mtoolsrc b/sos-code-article1/extra/mtoolsrc
new file mode 100644
index 0000000..df1a26e
--- /dev/null
+++ b/sos-code-article1/extra/mtoolsrc
@@ -0,0 +1,2 @@
+# For older versions of mtools, you may have to remove "filter"
+drive v: file="fd.img" 1.44M filter
diff --git a/sos-code-article1/extra/qemu-port-e9.diff b/sos-code-article1/extra/qemu-port-e9.diff
new file mode 100644
index 0000000..d8be044
--- /dev/null
+++ b/sos-code-article1/extra/qemu-port-e9.diff
@@ -0,0 +1,73 @@
+--- Makefile.target 17 Mar 2004 23:46:04 -0000 1.19
++++ Makefile.target 18 Mar 2004 14:20:29 -0000
+@@ -217,7 +217,8 @@
+ # must use static linking to avoid leaving stuff in virtual address space
+ VL_OBJS=vl.o osdep.o block.o monitor.o \
+ ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
+- fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
++ fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o \
++ port-e9.o
+ ifeq ($(TARGET_ARCH), ppc)
+ VL_OBJS+= hw.o
+ endif
+--- hw/pc.c 14 Mar 2004 21:46:48 -0000 1.2
++++ hw/pc.c 18 Mar 2004 14:20:29 -0000
+@@ -371,6 +371,7 @@
+ SB16_init();
+
+ fdctrl_init(6, 2, 0, 0x3f0, fd_table);
++ port_e9_init();
+
+ cmos_init(ram_size, boot_device);
+ }
+--- /dev/null 2003-01-30 11:24:37.000000000 +0100
++++ port-e9.c 2004-03-18 15:18:52.660493187 +0100
+@@ -0,0 +1,38 @@
++/*
++ * QEMU Port 0xe9 hack
++ *
++ * Copyright (c) 2000-2004 E. Marty, the bochs team, D. Decotigny
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++ * THE SOFTWARE.
++ */
++#include <stdio.h>
++#include <unistd.h>
++#include <inttypes.h>
++
++#include "vl.h"
++
++static void bochs_e9_write(void *opaque, uint32_t address, uint32_t data)
++{
++ write(fileno(stdout), &data, 1);
++}
++
++void port_e9_init ()
++{
++ register_ioport_write(0xe9, 1, 1, bochs_e9_write, NULL);
++}
+--- vl.h 17 Mar 2004 23:17:16 -0000 1.14
++++ vl.h 18 Mar 2004 14:29:06 -0000
+@@ -268,4 +268,7 @@
+ void term_flush(void);
+ void term_print_help(void);
+
++/* port-e9.c */
++void port_e9_init(void);
++
+ #endif /* VL_H */
diff --git a/sos-code-article1/extra/sos_bsect.lds b/sos-code-article1/extra/sos_bsect.lds
new file mode 100644
index 0000000..ac42f23
--- /dev/null
+++ b/sos-code-article1/extra/sos_bsect.lds
@@ -0,0 +1,61 @@
+/* Copyright (C) 2004, David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+SECTIONS
+{
+ /* ***********************************************
+ * The bootsector is here. We link it against the remaining of the kernel
+ * in order to automatically figure out its size that must be loaded
+ * from file to memory (see the load_size definition below)
+ */
+
+ /* If we use one, we put the boot sector here. We don't set its
+ * address to 0x7c000 (aka 0x7c00:0), since it reloads itself to
+ * 0x9f000, causing the 0x7c000 address to be meaningless too. So we
+ * chose to pretend that the address is 0x0, and to make a little
+ * address arithmetic in bootsect.S */
+ .bootsect 0x0 :
+ {
+ /* The code for the boot sector goes here */
+ *(.bootsect);
+
+ /* The load_size symbol contains the size of the area (in
+ * sectors, aka 512 Bytes) that the boot sector should copy from
+ * the disk. The bss section is not included since it uses 0
+ * bytes on disk */
+ load_size = .;
+ LONG((__e_load - __b_load + 511) >> 9);
+ /* ---> This is equivalent to ceil( (__e_load - __b_load) / 512 ) */
+
+ /* At offsets 511 and 512, we set the boot sector signature (AA55h) */
+ . = 0x1fe;
+ SHORT(0xAA55);
+ }
+}
+
+
+/* This is to avoid a cut/paste here. Please notice that a multiboot
+ * section WILL be inserted, which is NOT mandatory (we could have
+ * removed it without getting into trouble). Please note however that
+ * the *.bin files will NOT be multiboot compatible (they are not in ELF
+ * format): they are expected to be directly booted by the BIOS (or
+ * by the "chainloader" command of Grub). */
+INCLUDE ../support/sos.lds
+
+/* We overload the entry set in sos.lds, just to avoid an ld warning */
+ENTRY(sos_main);
diff --git a/sos-code-article1/hwcore/ioports.h b/sos-code-article1/hwcore/ioports.h
new file mode 100644
index 0000000..443acb7
--- /dev/null
+++ b/sos-code-article1/hwcore/ioports.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2004 All GPL'ed OS
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_IOPORTS_H_
+#define _SOS_IOPORTS_H_
+
+/**
+ * @ioports.h
+ *
+ * Intel-specific I/O space access routines.
+ */
+
+/* This macro allows to write to an I/O port */
+#define outb(value, port) \
+ __asm__ volatile ( \
+ "outb %b0,%w1" \
+ ::"a" (value),"Nd" (port) \
+ ) \
+
+// read one byte from port
+#define inb(port) \
+({ \
+ unsigned char _v; \
+ __asm__ volatile ( \
+ "inb %w1,%0" \
+ :"=a" (_v) \
+ :"Nd" (port) \
+ ); \
+ _v; \
+})
+
+#endif /* _SOS_IOPORTS_H_ */
diff --git a/sos-code-article1/sos.elf b/sos-code-article1/sos.elf
new file mode 100755
index 0000000..9dcfd43
--- /dev/null
+++ b/sos-code-article1/sos.elf
Binary files differ
diff --git a/sos-code-article1/sos.map b/sos-code-article1/sos.map
new file mode 100644
index 0000000..3ba39c3
--- /dev/null
+++ b/sos-code-article1/sos.map
@@ -0,0 +1,33 @@
+00201000 __b_kernel
+00200000 __b_load
+00205c00 __e_kernel
+00201bfb __e_load
+00201011 loop
+0020157f memcmp
+00201528 memcpy
+00201559 memset
+00201000 multiboot_entry
+00200000 multiboot_header
+00201a9f snprintf
+0020141d sos_bochs_hexdump
+002014e2 sos_bochs_printf
+0020123f sos_bochs_puthex
+0020121a sos_bochs_putstring
+00201210 sos_bochs_setup
+00201ad4 sos_main
+00201034 sos_x86_videomem_cls
+0020117e sos_x86_videomem_printf
+00201107 sos_x86_videomem_putchar
+00201077 sos_x86_videomem_putstring
+00201014 sos_x86_videomem_setup
+00201c00 stack
+00201000 start
+00201000 _start
+002016cd strcmp
+002015d9 strlen
+0020170f strncmp
+002015fe strnlen
+00201682 strzcat
+00201631 strzcpy
+00201b80 video
+00201770 vsnprintf
diff --git a/sos-code-article1/sos/assert.h b/sos-code-article1/sos/assert.h
new file mode 100644
index 0000000..a14ca0b
--- /dev/null
+++ b/sos-code-article1/sos/assert.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2004 The KOS Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ASSERT_H_
+#define _SOS_ASSERT_H_
+
+#include <drivers/bochs.h>
+#include <drivers/x86_videomem.h>
+
+/**
+ * If the expr is FALSE, print a message and halt the machine
+ */
+#define SOS_ASSERT_FATAL(expr) \
+ ({ \
+ int __res=(int)(expr); \
+ if (! __res) { \
+ asm("cli\n"); /* disable interrupts -- x86 only */ \
+ sos_bochs_printf("%s@%s:%d Assertion " # expr " failed\n", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ sos_x86_videomem_printf(24, 0, 12, \
+ "%s@%s:%d Assertion " # expr " failed", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ for (;;) asm("hlt;") ; /* Infinite loop, ie simple system halt */ \
+ } \
+ })
+
+
+#endif /* _SOS_ASSERT_H_ */
diff --git a/sos-code-article1/sos/errno.h b/sos-code-article1/sos/errno.h
new file mode 100644
index 0000000..f13e740
--- /dev/null
+++ b/sos-code-article1/sos/errno.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ERRNO_H_
+#define _SOS_ERRNO_H_
+
+/**
+ * @file errno.h
+ *
+ * SOS return value codes and errors.
+ */
+
+/* Positive values of the error codes */
+#define SOS_OK 0 /* No error */
+#define SOS_EINVAL 1 /* Invalid argument */
+#define SOS_ENOSUP 2 /* Operation not supported */
+#define SOS_EFATAL 255 /* Internal fatal error */
+
+/* A negative value means that an error occured. For
+ * example -SOS_EINVAL means that the error was "invalid
+ * argument" */
+typedef int sos_ret_t;
+
+#endif /* _SOS_ERRNO_H_ */
diff --git a/sos-code-article1/sos/klibc.c b/sos-code-article1/sos/klibc.c
new file mode 100644
index 0000000..277a15c
--- /dev/null
+++ b/sos-code-article1/sos/klibc.c
@@ -0,0 +1,271 @@
+/* Copyright (C) 2004 David Decotigny (with INSA Rennes for vsnprintf)
+ Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "klibc.h"
+
+/* For an optimized version, see BSD sources ;) */
+void *memcpy(void *dst0, const void *src0, register unsigned int size)
+{
+ char *dst;
+ const char *src;
+ for (dst = (char*)dst0, src = (const char*)src0 ;
+ size > 0 ;
+ dst++, src++, size--)
+ *dst = *src;
+ return dst0;
+}
+
+/* ditto */
+void *memset(void *dst0, register int c, register unsigned int length)
+{
+ char *dst;
+ for (dst = (char*) dst0 ;
+ length > 0 ;
+ dst++, length --)
+ *dst = (char)c;
+ return dst0;
+}
+
+int memcmp(const void *s1, const void *s2, sos_size_t len)
+{
+ const unsigned char *c1, *c2;
+ unsigned int i;
+
+ for (i = 0, c1 = s1, c2 = s2; i < len; i++, c1++, c2++)
+ {
+ if(*c1 != *c2)
+ return *c1 - *c2;
+ }
+
+ return 0;
+}
+
+
+unsigned int strlen(register const char *str)
+{
+ unsigned int retval = 0;
+
+ while (*str++)
+ retval++;
+
+ return retval;
+}
+
+
+unsigned int strnlen(const char * s, sos_size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */continue;
+
+ return sc - s;
+}
+
+
+char *strzcpy(register char *dst, register const char *src, register int len)
+{
+ int i;
+
+ if (len <= 0)
+ return dst;
+
+ for (i = 0; i < len; i++)
+ {
+ dst[i] = src[i];
+ if(src[i] == '\0')
+ return dst;
+ }
+
+ dst[len-1] = '\0';
+ return dst;
+}
+
+
+char *strzcat (char *dest, const char *src, sos_size_t n)
+{
+ char *res = dest;
+
+ for ( ; *dest ; dest++);
+
+ for ( ; *src ; src++, dest++) {
+ *dest = *src;
+ n--;
+ if (n <= 0)
+ break;
+ }
+
+ *dest = '\0';
+ return res;
+}
+
+int strcmp(register const char *s1, register const char *s2)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == 0)
+ return (0);
+
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
+
+
+int strncmp(register const char *s1, register const char *s2, register int len)
+{
+ char c1 = '\0', c2 = '\0';
+
+ while (len > 0)
+ {
+ c1 = (unsigned char) *s1++;
+ c2 = (unsigned char) *s2++;
+ if (c1 == '\0' || c1 != c2)
+ return c1 - c2;
+ len--;
+ }
+
+ return c1 - c2;
+}
+
+
+/* I (d2) borrowed and rewrote this for Nachos/INSA Rennes. Thanks to
+ them for having kindly allowed me to do so. */
+int vsnprintf(char *buff, sos_size_t len, const char * format, va_list ap)
+{
+ sos_size_t i, result;
+
+ if (!buff || !format || (len < 0))
+ return -1;
+
+#define PUTCHAR(thechar) \
+ do { \
+ if (result < len-1) \
+ *buff++ = (thechar); \
+ result++; \
+ } while (0)
+
+ result = 0;
+ for(i=0 ; format[i] != '\0' ; i++){
+ switch (format[i])
+ {
+ case '%':
+ i++;
+ switch(format[i])
+ {
+ case '%':
+ {
+ PUTCHAR('%');
+ break;
+ }
+ case 'i':;
+ case 'd':
+ {
+ int integer = va_arg(ap,int);
+ int cpt2 = 0;
+ char buff_int[16];
+
+ if (integer<0)
+ PUTCHAR('-');
+ /* Ne fait pas integer = -integer ici parce que INT_MIN
+ n'a pas d'equivalent positif (int = [-2^31, 2^31-1]) */
+
+ do {
+ int m10 = integer%10;
+ m10 = (m10 < 0)? -m10:m10;
+ buff_int[cpt2++]=(char)('0'+ m10);
+ integer=integer/10;
+ } while(integer!=0);
+
+ for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
+ PUTCHAR(buff_int[cpt2]);
+
+ break;
+ }
+
+ case 'c':
+ {
+ int value = va_arg(ap,int);
+ PUTCHAR((char)value);
+ break;
+ }
+
+ case 's':
+ {
+ char *string = va_arg(ap,char *);
+ if (! string)
+ string = "(null)";
+ for( ; *string != '\0' ; string++)
+ PUTCHAR(*string);
+ break;
+ }
+
+ case 'x':
+ {
+ unsigned int hexa = va_arg(ap,int);
+ unsigned int nb;
+ int i, had_nonzero = 0;
+ for(i=0 ; i < 8 ; i++)
+ {
+ nb = (unsigned int)(hexa << (i*4));
+ nb = (nb >> 28) & 0xf;
+ // Skip the leading zeros
+ if (nb == 0)
+ {
+ if (had_nonzero)
+ PUTCHAR('0');
+ }
+ else
+ {
+ had_nonzero = 1;
+ if (nb < 10)
+ PUTCHAR('0'+nb);
+ else
+ PUTCHAR('a'+(nb-10));
+ }
+ }
+ if (! had_nonzero)
+ PUTCHAR('0');
+ break;
+ }
+ break;
+
+ default:
+ PUTCHAR('%');
+ PUTCHAR(format[i]);
+ }
+ break;
+
+ default:
+ PUTCHAR(format[i]);
+ }
+ }
+
+ *buff = '\0';
+ return result;
+}
+
+
+int snprintf(char * buff, sos_size_t len, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ len = vsnprintf(buff, len, format, ap);
+ va_end(ap);
+
+ return len;
+}
diff --git a/sos-code-article1/sos/klibc.h b/sos-code-article1/sos/klibc.h
new file mode 100644
index 0000000..a8b9d49
--- /dev/null
+++ b/sos-code-article1/sos/klibc.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_KLIBC_H_
+#define _SOS_KLIBC_H_
+
+/**
+ * @file klibc.h
+ *
+ * Basic libc-style support for common useful functions (string.h,
+ * stdarg.h), some with slight non-standard behavior (see comments).
+ */
+
+#include <sos/types.h>
+
+/* string.h functions */
+
+void *memcpy(void *dst, const void *src, register unsigned int size ) ;
+void *memset(void *dst, register int c, register unsigned int length ) ;
+int memcmp(const void *s1, const void *s2, sos_size_t n);
+
+unsigned int strlen( register const char *str) ;
+unsigned int strnlen(const char * s, sos_size_t maxlen);
+
+/**
+ * @note Same as strncpy(), with a slightly different semantic.
+ * Actually, strncpy(3C) says " The result will not be null-terminated
+ * if the length of 'from' is n or more.". Here, 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcpy( register char *dst, register const char *src,
+ register int len ) ;
+
+/**
+ * @note Same as strncat(), with the same semantic : 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcat (char *dest, const char *src,
+ const sos_size_t len);
+
+int strcmp(register const char *s1, register const char *s2 );
+int strncmp(register const char *s1, register const char *s2,
+ register int len );
+
+/* Basic stdarg.h macros. Taken from gcc support files */
+#define __GNUC_VA_LIST
+typedef void *__gnuc_va_list;
+typedef __gnuc_va_list va_list;
+#define __va_rounded_size(TYPE) \
+ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+#define va_start(AP, LASTARG) \
+ (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG)))
+#define va_end(AP) \
+ ((void)0)
+#define va_arg(AP, TYPE) \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
+ *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
+#define __va_copy(dest, src) \
+ (dest) = (src)
+
+/* stdarg.h functions. There might be a non-standard behavior: there
+ will always be a trailing '\0' in the resulting string */
+int vsnprintf(char *, sos_size_t, const char *, va_list);
+int snprintf(char *, sos_size_t, const char *, /*args*/ ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+#endif /* _SOS_KLIBC_H_ */
diff --git a/sos-code-article1/sos/main.c b/sos-code-article1/sos/main.c
new file mode 100644
index 0000000..a5adb54
--- /dev/null
+++ b/sos-code-article1/sos/main.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* Include definitions of the multiboot standard */
+#include <bootstrap/multiboot.h>
+#include <sos/klibc.h>
+#include <sos/assert.h>
+#include <drivers/x86_videomem.h>
+#include <drivers/bochs.h>
+
+
+
+/* The C entry point of our operating system */
+void sos_main(unsigned long magic, unsigned long addr)
+{
+ unsigned i;
+
+ /* Grub sends us a structure, called multiboot_info_t with a lot of
+ precious informations about the system, see the multiboot
+ documentation for more information. */
+ multiboot_info_t *mbi;
+ mbi = (multiboot_info_t *) addr;
+
+ /* Setup bochs and console, and clear the console */
+ sos_bochs_setup();
+
+ sos_x86_videomem_setup();
+ sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
+
+ /* Greetings from SOS */
+ if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
+ /* Loaded with Grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
+ "SOS", ',',
+ (unsigned)(mbi->mem_upper >> 10) + 1,
+ (unsigned)mbi->mem_upper);
+ else
+ /* Not loaded with grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome to SOS");
+
+ sos_bochs_putstring("Message in a bochs\n");
+
+
+ /* An operatig system never ends */
+ for (;;)
+ continue;
+
+ return;
+}
diff --git a/sos-code-article1/sos/types.h b/sos-code-article1/sos/types.h
new file mode 100644
index 0000000..de54a9c
--- /dev/null
+++ b/sos-code-article1/sos/types.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_TYPES_H_
+#define _SOS_TYPES_H_
+
+/**
+ * @file types.h
+ *
+ * SOS basic types definition
+ */
+
+/** Memory size of an object (positive) */
+typedef unsigned int sos_size_t;
+
+/** Low-level sizes */
+typedef unsigned long int sos_ui32_t; /* 32b unsigned */
+typedef unsigned short int sos_ui16_t; /* 16b unsigned */
+typedef unsigned char sos_ui8_t; /* 8b unsigned */
+
+typedef enum { FALSE=0, TRUE } sos_bool_t;
+
+/** Not a proper type, but highly useful with basic type
+ manipulations */
+#define NULL ((void*)0)
+
+#endif /* _SOS_TYPES_H_ */
diff --git a/sos-code-article1/support/build_image.sh b/sos-code-article1/support/build_image.sh
new file mode 100755
index 0000000..43929cd
--- /dev/null
+++ b/sos-code-article1/support/build_image.sh
@@ -0,0 +1,215 @@
+#!/bin/sh
+# Copyright (C) 2003, David Decotigny
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# 1) What does it do ?
+#
+# 1) Check where Grub is installed (lookup_grub)
+# 2) Assign some local variables using the shell script arguments.
+# a) Argument 1 : the destination (either a file or a drive, like a:)
+# b) Argument 2 : the loader (i.e kernel)
+# c) Argument 3 : options passed to the loader
+# d) Argument 4 : the modules (that can be loaded optionally by Grub)
+# 3) Test whether destination is a drive or a file
+# 4) Create the directory structure inside the drive
+# 5) Copy the loader in the drive
+# 6) Generate the 'menu.txt' file used by Grub to generate the boot menu
+# 7) Copy all modules
+# 8) Copy the menu.txt file
+#
+# 2) Why is it so complex ?
+# Because it must support various Grub/mtools installations and versions
+#
+# In fact, this shell script is used in the KOS (kos.enix.org)
+# project. This operating system consists in a loader and many many
+# modules that are linked together at boot time. It is much more
+# complex that a simple monolithic kernel.
+#
+# For your simple monolithic kernel, you only need to give argument 1
+# and 2.
+
+print_usage () {
+ echo "Usage: $0 [X:|image] path/to/loader option path/to/modules..."
+ echo " where X: is a valid floppy drive on your computer"
+ echo " where image is any file name"
+ exit 1
+}
+
+grub_dirs_common="/usr/local/share/grub/i386-freebsd /usr/local/share/grub/i386-pc /usr/share/grub/i386-pc /usr/lib/grub/i386-pc /usr/local/grub /usr/share/grub/i386-redhat /usr/local/src/grub-0.5.94 $HOME/share/grub/i386-pc/"
+sbin_grub_path="/usr/local/sbin /usr/sbin /sbin $HOME/sbin"
+
+PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
+export PATH
+
+MTOOLSRC=mtoolsrc
+export MTOOLSRC
+
+# Redefined variables
+FLOPPY_DRIVE=A:
+IMG_FNAME=fd.img
+
+##
+## Format disk image
+##
+init_image () {
+ echo "Initialize disk image $IMG_FILE..."
+ if [ ! -f $IMG_FNAME ] ; then
+ dd if=/dev/zero of=$IMG_FNAME bs=18k count=80 1>/dev/null 2>&1
+ fi
+
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M filter" > $MTOOLSRC
+
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M" > $MTOOLSRC
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\"" > $MTOOLSRC
+ mformat U:
+ fi
+ fi
+}
+
+
+##
+## Format (real) floppy disk
+##
+init_floppy () {
+ echo "Formatting floppy..."
+ mformat $FLOPPY_DRIVE || exit 1
+}
+
+
+lookup_grub () {
+ # Look for a correct GRUBDIR
+ for d in $grub_dirs_common ; do
+ if [ -d $d ] ; then
+ GRUBDIR=$d
+ break
+ fi
+ done
+
+ # Try to guess with locate
+ if [ ! -d "$GRUBDIR" ] ; then
+ GRUBDIR=`locate stage2 | head -1 | xargs dirname 2>/dev/null`
+ fi
+
+ # Look for a correct sbin/grub
+ for d in $sbin_grub_path ; do
+ if [ -x $d/grub ] ; then
+ SBIN_GRUB=$d/grub
+ break
+ fi
+ done
+
+ if [ -d "$GRUBDIR" -a -x "$SBIN_GRUB" ] ; then
+ echo "Found correct grub installation in $GRUBDIR"
+ echo "Found correct /sbin/grub at $SBIN_GRUB"
+ else
+ echo "Couldn't find a correct grub installation."
+ exit 1
+ fi
+}
+
+##
+## setup_disk [drive]
+## => setup disk directory structure / copy files
+##
+setup_disk () {
+ echo "Setup destination disk..."
+
+ mmd $1/boot
+ mmd $1/boot/grub
+
+ if [ -d $GRUBDIR/stage1 ] ; then
+ mcopy $GRUBDIR/stage1/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2/stage2 $1/boot/grub/
+ else
+ mcopy $GRUBDIR/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2 $1/boot/grub/
+ fi
+ mmd $1/system
+ mmd $1/modules
+
+ $SBIN_GRUB --batch <<EOT 1>/dev/null 2>/dev/null || exit 1
+device (fd0) $IMG_FNAME
+install (fd0)/boot/grub/stage1 (fd0) (fd0)/boot/grub/stage2 p (fd0)/boot/grub/menu.txt
+quit
+EOT
+}
+
+
+
+#################################################
+## Real start
+##
+#[ "$#" -lt 3 ] && print_usage
+
+lookup_grub
+
+dest="$1" ; shift
+loader_fname="$1" ; shift
+options="$1" ; shift
+modules="$*"
+
+# Init destination disk
+case x$dest in
+ x*:)
+ drive=$dest
+ IMG_FNAME=$dest
+ FLOPPY_DRIVE=$dest
+ init_floppy
+ ;;
+ x*)
+ drive=U:
+ IMG_FNAME=$dest
+ init_image
+ ;;
+esac
+
+# Create directory structure
+setup_disk $drive
+
+# Copy the loader
+mcopy -bo $loader_fname $drive/system/`basename $loader_fname`
+
+# Generate the menu.txt file
+rm -f menu.txt
+cat <<EOF > menu.txt
+timeout 0
+default 0
+title Simple OS
+root (fd0)
+kernel /system/`basename $loader_fname` $options
+EOF
+
+# Copy the modules
+for f in $modules ; do
+ if [ ! -f $f ] ; then
+ echo "ERROR: module $f not correctly compiled in."
+ exit 1
+ fi
+ if ! mcopy -bo $f $drive/modules/`basename $f` ; then
+ echo "ERROR: module $f could not be transferred to floppy."
+ exit 1
+ fi
+ echo module /modules/`basename $f` >> menu.txt
+done
+
+# Transfers the menu.txt file to floppy
+mcopy -bo menu.txt $drive/boot/grub/
diff --git a/sos-code-article1/support/sos.lds b/sos-code-article1/support/sos.lds
new file mode 100644
index 0000000..4d87061
--- /dev/null
+++ b/sos-code-article1/support/sos.lds
@@ -0,0 +1,107 @@
+/* Copyright (C) 2003, Thomas Petazzoni
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* We generate binary in the ELF format */
+OUTPUT_FORMAT("elf32-i386","elf32-i386","elf32-i386");
+
+/* The entry point is _start (defined in boot.S) */
+ENTRY(_start)
+
+/* The architecture is i386 */
+OUTPUT_ARCH("i386")
+
+SECTIONS
+{
+ /* our kernel is loaded at 0x200000 */
+ . = 0x200000;
+ __b_load = .;
+
+ /* the multiboot header MUST come early enough in the output
+ object file */
+ .multiboot :
+ {
+ /* The multiboot section (containing the multiboot header)
+ goes here */
+ *(.multiboot);
+
+ /*
+ * With the following line, we force this section to be
+ * allocated in the output file as soon as possible, no matter
+ * when the file containing the multiboot header (multiboot.S)
+ * is compiled. This is to conform to the multiboot spec, which
+ * says "The Multiboot header must be contained completely
+ * within the first 8192 bytes of the OS image, and must be
+ * longword (32-bit) aligned."
+ */
+ LONG(0);
+ }
+
+ /* Defines a symbol '__b_kernel to mark the start of the kernel
+ code/data */
+ . = ALIGN(4096);
+ __b_kernel = .;
+
+ /* Beginning of the text section */
+ .text ALIGN(4096) :
+ {
+ /* This section includes the code */
+ *(.text*)
+ /* Defines the 'etext' and '_etext' at the end */
+ PROVIDE(etext = .);
+ PROVIDE(_etext = .);
+ }
+
+ /* Beginning of the data section */
+ .data . :
+ { *(.data*)
+ PROVIDE(edata = .);
+ PROVIDE(_edata = .);
+ }
+
+ /* Beginning of the read-only data section */
+ .rodata . :
+ { *(.rodata*)
+ PROVIDE(erodata = .);
+ PROVIDE(_erodata = .);
+ }
+ /* We take note of the end of the data to load */
+ __e_load = .;
+
+ /* Beginning of the BSS section (global uninitialized data) */
+ .bss SIZEOF(.rodata) + ADDR(.rodata) :
+ { *(.bss)
+ *(COMMON)
+ PROVIDE(ebss = .);
+ PROVIDE(_ebss = .);
+ }
+
+ /* We take note of the end of the kernel */
+ __e_kernel = .;
+
+ /* We don't care of the note, indent, comment, etc.. sections
+ generated by gcc */
+ /DISCARD/ :{
+ *(.note*)
+ *(.indent)
+ *(.comment)
+ *(.stab)
+ *(.stabstr)
+ }
+
+}
+
diff --git a/sos-code-article2/INSTALL b/sos-code-article2/INSTALL
new file mode 100644
index 0000000..7c7d619
--- /dev/null
+++ b/sos-code-article2/INSTALL
@@ -0,0 +1,118 @@
+
+ SOS: A Simple Operating System
+
+ Compilation/Installation/Test instructions
+
+
+Compilation
+===========
+
+IMPORTANT
+---------
+
+Don't forget to run 'make clean' before 'make' after you have modified
+any source or header file(s).
+
+
+On a x86 host where grub is correctly installed
+-----------------------------------------------
+
+Simply run 'make'
+
+
+On a non-x86 host (without grub of course !)
+--------------------------------------------
+
+See extra/README
+
+
+On an x86 host without Grub, or with a buggy Grub
+-------------------------------------------------
+
+See extra/README
+
+How do I know I have a buggy grub installation ? Answer: in the qemu
+PC emulator, Grub hangs while loading the kernel
+
+
+Installation
+============
+
+Nothing special to do besides compiling
+
+
+Test the SOS Kernel
+===================
+
+On a x86 real machine with Grub installed
+-----------------------------------------
+
+ 1st method
+ => Boot the sos.elf file (append 'kernel=<path_to>sos.elf' in the
+ menu.lst or type it on Grub's command line) from a hard disk, a
+ floppy, or from the network
+
+ 2nd method
+ => Copy the file 'fd.img' to a floppy and boot from it
+
+
+On a x86 real machine without Grub installed
+--------------------------------------------
+
+ 1st method
+ => see extra/README to compile with the grub floppy image we provide,
+ copy the file 'fd.img' to a floppy, and boot from it
+
+ 2nd method
+ => see extra/README to compile with the boot sector we provide (up to
+ article 2 only), copy the file 'extra/sos_bsect.img' to a floppy,
+ and boot from it
+
+
+Inside a PC emulator (x86 and non-x86 hosts)
+--------------------------------------------
+
+Tested on both the bochs emulator (x86/linux, sparc/solaris and
+ppc/linux hosts, 'apt-get install bochs-x vgabios' on debian
+testing/unstable), and the qemu system emulator (with libsdl
+installed: 'apt-get install libsdl1.2-dev' on debian
+testing/unstable).
+
+ 1/ Grub is installed on the host (x86 hosts only)
+ - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ bochs: boot from the file 'fd.img'. Example of a ~/.bochsrc:
+ floppya: 1_44=/home/d2/sos/fd.img, status=inserted
+ romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
+ vgaromimage: /usr/share/vgabios/vgabios.bin
+ megs:63 # 63 Mo de RAM
+
+ qemu: run 'qemu -fda fd.img'
+ If grub hangs while loading the kernel, please go to method 2/
+
+ 2/ Grub is not installed (all hosts)
+ - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the Grub floppy
+ image we provide, and:
+
+ bochs: boot from the file 'fd.img'
+
+ qemu: run 'qemu -fda fd.img'
+
+ 3/ Bonus: boot with the bootsector we provide (all hosts, up to art. 2 ONLY !)
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the boot sector we
+ provide, and:
+
+ bochs: boot from the file 'extra/sos_bsect.img'
+
+ qemu: run 'qemu -fda extra/sos_qemu.img'
+
+ NOTE: After article 2, this way of booting is not supported: please
+ use the method 2/ above.
+
+
+--
+David Decotigny
diff --git a/sos-code-article2/LICENSE b/sos-code-article2/LICENSE
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/sos-code-article2/LICENSE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/sos-code-article2/Makefile b/sos-code-article2/Makefile
new file mode 100644
index 0000000..fd1fa89
--- /dev/null
+++ b/sos-code-article2/Makefile
@@ -0,0 +1,56 @@
+CC=i586-elf-gcc
+LD=i586-elf-ld
+CFLAGS = -Wall -nostdlib -nostdinc -ffreestanding -DKERNEL_SOS
+LDFLAGS = --warn-common
+OBJECTS = bootstrap/multiboot.o \
+ hwcore/idt.o hwcore/gdt.o \
+ hwcore/exception.o hwcore/exception_wrappers.o \
+ hwcore/irq.o hwcore/irq_wrappers.o hwcore/i8259.o \
+ hwcore/i8254.o drivers/x86_videomem.o drivers/bochs.o \
+ sos/klibc.o sos/main.o
+
+KERNEL_OBJ = sos.elf
+MULTIBOOT_IMAGE = cdrom.iso
+PWD := $(shell pwd)
+
+# Main target
+all: $(MULTIBOOT_IMAGE)
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ)
+ # ./support/build_image.sh $@ $<
+ if [ ! -e cdrom/boot/grub/stage2_eltorito ]; then \
+ mkdir -p cdrom/boot/grub; \
+ echo "Please copy grub's stage2_eltorito to cdrom/boot/grub."; \
+ exit -1; \
+ fi
+ cp $(KERNEL_OBJ) cdrom
+ echo timeout 0 > cdrom/boot/grub/menu.lst
+ echo title Simple OS >> cdrom/boot/grub/menu.lst
+ echo kernel /$(KERNEL_OBJ) >> cdrom/boot/grub/menu.lst
+ genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 \
+ -boot-info-table -input-charset ascii -A SOS -o $(MULTIBOOT_IMAGE) cdrom
+
+$(KERNEL_OBJ): $(OBJECTS) ./support/sos.lds
+ $(LD) $(LDFLAGS) -T ./support/sos.lds -o $@ $(OBJECTS)
+ -nm -C $@ | cut -d ' ' -f 1,3 > sos.map
+
+-include .mkvars
+
+# Create objects from C source code
+%.o: %.c
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -o $@
+
+# Create objects from assembler (.S) source code
+%.o: %.S
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -DASM_SOURCE=1 -o $@
+
+# Clean directory
+clean:
+ $(RM) *.img *.iso *.o mtoolsrc *~ menu.txt *.img *.elf *.bin *.map
+ $(RM) *.log *.out bochs*
+ $(RM) bootstrap/*.o bootstrap/*~
+ $(RM) drivers/*.o drivers/*~
+ $(RM) hwcore/*.o hwcore/*~
+ $(RM) sos/*.o sos/*~
+ $(RM) support/*~
+ $(RM) extra/*~
diff --git a/sos-code-article2/README b/sos-code-article2/README
new file mode 100644
index 0000000..efbbc89
--- /dev/null
+++ b/sos-code-article2/README
@@ -0,0 +1,90 @@
+
+ SOS: A Simple Operating System
+
+
+This is SOS, a Simple Operating System for i386-family
+processors. This is as simple as possible to show a way to program a
+basic Operating System on real common hardware (PC). The code should
+be easily readable and understandable thanks to frequent comments, and
+references to external documentation. We chose to implement the basic
+features of an OS, thus making design decisions targetting towards
+simplicity of understanding, covering most of the OS classical
+concepts, but not aiming at proposing yet another full-fledged
+competitive OS (Linux is quite good at it). However, for those who
+would like to propose some enhancements, we are open to any code
+suggestions (patches only, please). And yes, there might be bugs in
+the code, so please send us any bug report, and/or patches !
+
+The OS comes as a set of articles (in french) to be published in the
+journal "Linux Magazine France". Each month, the part of the code
+related to the current article's theme is released (see VERSION file),
+and the resulting OS can be successfully compiled and run, by booting
+it from a floppy on a real machine (tested AMD k7, Cyrix and Intel P4
+pentiums), or through an x86 emulator (bochs or qemu). The resulting
+OS is available as a multiboot compliant ELF kernel (sos.elf) and as a
+floppy image (fd.img). It provides a very very very basic demo whose
+aim is to understand how everything works, not to animate sprites on
+the screen with 5:1 dolby sound.
+
+The initial technical features and lack-of-features of the OS are:
+ - monolithic kernel, fully interruptible, non-preemptible (big kernel
+ lock), target machines = i386 PC or better
+ - compiles on any host where the gcc/binutils toolchain (target
+ i586-gnu) is available. Can be tested on real i486/pentium
+ hardware, or on any host that can run an i486/pentium PC emulator
+ (bochs or qemu)
+ - kernel loaded by grub, or by a sample bootsector (up to article 2
+ ONLY)
+ - clear separation of physical memory and virtual memory concepts,
+ even inside the kernel: no identity-mapping of the physical memory
+ inside the kernel (allows to move virtual mappings of kernel pages
+ at run-time, eg to free ISA DMA pages, and to avercome the 4G RAM
+ barrier)
+ - slab-type kernel memory allocation
+ - no swap, no reverse mapping
+ - VERY simple drivers: keyboard, x86 video memory, IDE disks
+ - logical devices: partitions, FAT filesystem, "hard-coded"
+ mountpoints only (~ MSDOS)
+ - no network stack
+ - user-level features: ELF loader (no shared libraries), processes,
+ user threads (kernel-level scheduling only), mmap API, basic VFS
+
+To understand where to look at for what, here is a brief description:
+ - Makefile: the (ONLY) makefile of the OS. Targets are basically
+ 'all' and 'clean'
+ - bootstrap/ directory: code to load the kernel. Both the stuff
+ needed for a multiboot-compliant loader (eg grub) AND a bootsector
+ are provided. The bootsector may only be used up to article 2.
+ - sos/ directory: the entry routine for the kernel (main.c), various
+ systemwide header files, a set of common useful C routines
+ ("nano-klibc"), and kernel subsystems (kernel memory management,
+ etc...)
+ - hwcore/ directory: Low-level CPU- and kernel-related routines
+ (interrupt/exception management, translation tables and segment
+ registers, ...)
+ - drivers/ directory: basic kernel drivers for various (non CPU)
+ devices (keyboard, x86 video memory, bochs 0xe9 port, ...). Used
+ mainly for debugging
+ - support/ directory: scripts and configuration files to build the
+ floppy images
+ - extra/ directory: a set of configuration files to be customized for
+ non-x86 host installations (yes, we primarily develop SOS on a ppc, for
+ the x86 target of course), or for grub-less installations. See
+ README file in this directory.
+
+The code is licensed under the terms of the GNU GPL version 2 (see
+LICENSE file).
+
+Enjoy !
+
+ David Decotigny, Thomas Petazzoni, the Kos team
+ http://sos.enix.org/
+ http://david.decotigny.free.fr/
+ http://kos.enix.org/~thomas/
+ http://kos.enix.org/
+
+
+--
+David Decotigny
+
+PS: Made with a Mac.
diff --git a/sos-code-article2/VERSION b/sos-code-article2/VERSION
new file mode 100644
index 0000000..be4a929
--- /dev/null
+++ b/sos-code-article2/VERSION
@@ -0,0 +1,11 @@
+SOS -- Simple OS
+Copyright (C) 2003,2004 The SOS Team (David Decotigny & Thomas Petazzoni)
+
+Version "Article 2" -- Basic interrupt & processor exception management
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See the LICENSE file included in the distribution.
diff --git a/sos-code-article2/bootstrap/multiboot.S b/sos-code-article2/bootstrap/multiboot.S
new file mode 100644
index 0000000..4a7c65b
--- /dev/null
+++ b/sos-code-article2/bootstrap/multiboot.S
@@ -0,0 +1,74 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+
+/* The operating system is booted by Grub, so we almost have nothing
+ to do to boot it. We only have to conform to the Multiboot
+ standard, as defined by the Grub documentation */
+
+#define ASM 1
+/* The multiboot.h header contains a lot of multiboot standard
+ definitions */
+#include "multiboot.h"
+
+ /* The multiboot header itself. It must come first. */
+.section ".multiboot"
+ /* Multiboot header must be aligned on a 4-byte boundary */
+ .align 4
+multiboot_header:
+ /* magic= */ .long MULTIBOOT_HEADER_MAGIC
+ /* flags= */ .long MULTIBOOT_HEADER_FLAGS
+ /* checksum= */ .long -(MULTIBOOT_HEADER_MAGIC \
+ +MULTIBOOT_HEADER_FLAGS)
+ /* header_addr= */ .long multiboot_header
+ /* load_addr= */ .long __b_kernel
+ /* load_end_addr=*/ .long __e_load
+ /* bss_end_addr= */ .long __e_kernel
+ /* entry_addr= */ .long multiboot_entry
+
+/* Here is the beginning of the code of our operating system */
+.text
+
+.globl start, _start
+start:
+_start:
+multiboot_entry:
+ /* Set up a stack */
+ movl $(stack + MULTIBOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Set EFLAGS to 0 */
+ pushl $0
+ /* pop stack into the EFLAGS register */
+ popf
+
+ /* Push the magic and the address on the stack, so that they
+ will be the parameters of the cmain function */
+ pushl %ebx
+ pushl %eax
+
+ /* Call the cmain function (os.c) */
+ call EXT_C(sos_main)
+
+ /* Should never get there */
+loop:
+ hlt
+ jmp loop
+
+ /* Here is the stack */
+.comm stack, MULTIBOOT_STACK_SIZE
diff --git a/sos-code-article2/bootstrap/multiboot.h b/sos-code-article2/bootstrap/multiboot.h
new file mode 100644
index 0000000..bee676d
--- /dev/null
+++ b/sos-code-article2/bootstrap/multiboot.h
@@ -0,0 +1,129 @@
+#ifndef __MULTIBOOT_H__
+#define __MULTIBOOT_H__
+
+/* multiboot.h - the header for Multiboot */
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Macros. */
+
+/* The magic number for the Multiboot header. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* The flags for the Multiboot header. */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* The magic number passed by a Multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (16KB). */
+#define MULTIBOOT_STACK_SIZE 0x4000
+
+#define MULTIBOOT_CMDLINE 4
+#define MULTIBOOT_MODS 8
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* Do not include here in boot.S. */
+
+
+
+/* Types. */
+
+/* The Multiboot header. */
+typedef struct multiboot_header
+{
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* The symbol table for a.out. */
+typedef struct aout_symbol_table
+{
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* The section header table for ELF. */
+typedef struct elf_section_header_table
+{
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* The Multiboot information. */
+typedef struct multiboot_info
+{
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union
+ {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+ unsigned long drives_length;
+ unsigned long drives_addr;
+} multiboot_info_t;
+
+/* The module structure. */
+typedef struct module
+{
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* The memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map
+{
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+void dump_multiboot_info(multiboot_info_t *mbi);
+
+#endif /* ! ASM */
+
+#endif /* __MULTIBOOT_H__ */
diff --git a/sos-code-article2/cdrom/boot/grub/menu.lst b/sos-code-article2/cdrom/boot/grub/menu.lst
new file mode 100644
index 0000000..351100d
--- /dev/null
+++ b/sos-code-article2/cdrom/boot/grub/menu.lst
@@ -0,0 +1,3 @@
+timeout 0
+title Simple OS
+kernel /sos.elf
diff --git a/sos-code-article2/cdrom/boot/grub/stage2_eltorito b/sos-code-article2/cdrom/boot/grub/stage2_eltorito
new file mode 100644
index 0000000..6d82f08
--- /dev/null
+++ b/sos-code-article2/cdrom/boot/grub/stage2_eltorito
Binary files differ
diff --git a/sos-code-article2/cdrom/sos.elf b/sos-code-article2/cdrom/sos.elf
new file mode 100755
index 0000000..0898db5
--- /dev/null
+++ b/sos-code-article2/cdrom/sos.elf
Binary files differ
diff --git a/sos-code-article2/drivers/bochs.c b/sos-code-article2/drivers/bochs.c
new file mode 100644
index 0000000..db18599
--- /dev/null
+++ b/sos-code-article2/drivers/bochs.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <hwcore/ioports.h>
+#include <sos/klibc.h>
+
+#include "bochs.h"
+
+/* This is a special hack that is only useful when running the
+ operating system under the Bochs emulator. */
+#define SOS_BOCHS_IOPORT 0xe9
+
+sos_ret_t sos_bochs_setup(void)
+{
+ return SOS_OK;
+}
+
+
+#define sos_bochs_putchar(chr) \
+ outb((chr), SOS_BOCHS_IOPORT)
+
+sos_ret_t sos_bochs_putstring(const char* str)
+{
+ for ( ; str && (*str != '\0') ; str++)
+ sos_bochs_putchar(*str);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes)
+{
+ unsigned c;
+
+#define BOCHS_PRTHEX(q) \
+ ({ unsigned char r; if ((q) >= 10) r='a'+(q)-10; \
+ else r='0'+(q); sos_bochs_putchar(r); })
+
+ switch (nbytes)
+ {
+ case 4:
+ c = (val >> 24) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 3:
+ c = (val >> 16) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 2:
+ c = (val >> 8) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 1:
+ c = val & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes)
+{
+ int offs;
+ for (offs = 0 ; offs < nbytes ; offs++)
+ {
+ const unsigned char *c;
+
+ if ((offs % 16) == 0)
+ {
+ sos_bochs_putstring("0x");
+ sos_bochs_puthex(offs, 4);
+ }
+
+ if ((offs % 8) == 0)
+ sos_bochs_putstring(" ");
+
+ c = (const unsigned char*)(addr + offs);
+ sos_bochs_puthex(*c, 1);
+ sos_bochs_putstring(" ");
+
+ if (((offs + 1) % 16) == 0)
+ sos_bochs_putstring("\n");
+ }
+
+ if (offs % 16)
+ sos_bochs_putstring("\n");
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_bochs_putstring(buff);
+}
diff --git a/sos-code-article2/drivers/bochs.h b/sos-code-article2/drivers/bochs.h
new file mode 100644
index 0000000..310b023
--- /dev/null
+++ b/sos-code-article2/drivers/bochs.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_BOCHS_H_
+#define _SOS_BOCHS_H_
+
+/**
+ * @file bochs.h
+ *
+ * If you compiled Bochs with the --enable-e9-hack, then any character
+ * printed to the 0xE9 I/O port is printed to the xterm that is
+ * running Bochs. This may appear to be a detail, but in fact, this
+ * functionnality is *VERY* precious for debugging purposes. This
+ * """driver""" handles this feature.
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+
+sos_ret_t sos_bochs_setup(void);
+
+sos_ret_t sos_bochs_putstring(const char* str);
+
+/** Print the least signficant 32 (nbytes == 4), 24 (nbytes == 3), 16
+ (nbytes == 2) or 8 (nbytes == 1) bits of val in hexadecimal. */
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes);
+
+/** hexdump-style pretty printing */
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#endif
diff --git a/sos-code-article2/drivers/x86_videomem.c b/sos-code-article2/drivers/x86_videomem.c
new file mode 100644
index 0000000..cc4b79c
--- /dev/null
+++ b/sos-code-article2/drivers/x86_videomem.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <sos/klibc.h>
+#include <hwcore/ioports.h>
+
+#include "x86_videomem.h"
+
+/* The text video memory starts at address 0xB8000. Odd bytes are the
+ ASCII value of the character, even bytes are attribute for the
+ preceding character. */
+#define VIDEO 0xb8000
+
+
+/* Console screen size */
+#define LINES 25
+#define COLUMNS 80
+
+
+/** The structure of a character element in the video memory. @see
+ http://webster.cs.ucr.edu/AoA DOS edition chapter 23 */
+typedef struct {
+ unsigned char character;
+ unsigned char attribute;
+} __attribute__ ((packed)) x86_video_mem[LINES*COLUMNS];
+
+
+
+/** The base pointer for the video memory */
+static volatile x86_video_mem *video = (volatile x86_video_mem*)VIDEO;
+
+sos_ret_t sos_x86_videomem_setup(void)
+{
+ /*
+ * Hide cursor. @see Ralf Brown's interrupt (and port) list
+ * http://www-2.cs.cmu.edu/~ralf/files.html
+ */
+#define CRT_REG_INDEX 0x3d4
+#define CRT_REG_DATA 0x3d5
+
+ /* CRT index port => ask for access to register 0xa ("cursor
+ start") */
+ outb(0x0a, CRT_REG_INDEX);
+
+ /* (RBIL Tables 708 & 654) CRT Register 0xa => bit 5 = cursor OFF */
+ outb(1 << 5, CRT_REG_DATA);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute)
+{
+ /* Clears the screen */
+ int i;
+ for(i = 0 ; i < LINES*COLUMNS ; i++)
+ {
+ (*video)[i].character = 0;
+ (*video)[i].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ for ( ; str && *str && (video_offs < LINES*COLUMNS) ; str++, video_offs++)
+ {
+ (*video)[video_offs].character = (unsigned char)*str;
+ (*video)[video_offs].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ (*video)[video_offs].character = c;
+ (*video)[video_offs].attribute = attribute;
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_x86_videomem_putstring(row, col, attribute, buff);
+}
diff --git a/sos-code-article2/drivers/x86_videomem.h b/sos-code-article2/drivers/x86_videomem.h
new file mode 100644
index 0000000..31a9dfc
--- /dev/null
+++ b/sos-code-article2/drivers/x86_videomem.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_X86_VIDEOMEM_H_
+#define _SOS_X86_VIDEOMEM_H_
+
+/**
+ * @file x86_videomem.h
+ *
+ * On x86 PC platforms, the text mode screen memory (and CGA/EGA/VGA
+ * too) is mapped into physical memory. This file handles access to
+ * this screen, supposed to be set in text-mode, through this memory
+ * area. All the functions below print the characters directly to the
+ * memory, without interpreting the escaped characters (such as \n,
+ * \r...)
+ */
+
+#include <sos/errno.h>
+
+/**
+ * x86 video attributes
+ * See http://webster.cs.ucr.edu/AoA/DOS/ch23/CH23-1.html
+ */
+/* Normal and Dark/Light foreground */
+#define SOS_X86_VIDEO_FG_BLACK 0
+#define SOS_X86_VIDEO_FG_DKGRAY 8
+#define SOS_X86_VIDEO_FG_BLUE 1
+#define SOS_X86_VIDEO_FG_LTBLUE 9
+#define SOS_X86_VIDEO_FG_GREEN 2
+#define SOS_X86_VIDEO_FG_LTGREEN 10
+#define SOS_X86_VIDEO_FG_CYAN 3
+#define SOS_X86_VIDEO_FG_LTCYAN 11
+#define SOS_X86_VIDEO_FG_RED 4
+#define SOS_X86_VIDEO_FG_LTRED 12
+#define SOS_X86_VIDEO_FG_MAGENTA 5
+#define SOS_X86_VIDEO_FG_LTMAGENTA 13
+#define SOS_X86_VIDEO_FG_BROWN 6
+#define SOS_X86_VIDEO_FG_YELLOW 14
+#define SOS_X86_VIDEO_FG_LTGRAY 7
+#define SOS_X86_VIDEO_FG_WHITE 15
+/* Background */
+#define SOS_X86_VIDEO_BG_BLACK (0 << 4)
+#define SOS_X86_VIDEO_BG_BLUE (1 << 4)
+#define SOS_X86_VIDEO_BG_GREEN (2 << 4)
+#define SOS_X86_VIDEO_BG_CYAN (3 << 4)
+#define SOS_X86_VIDEO_BG_RED (4 << 4)
+#define SOS_X86_VIDEO_BG_MAGENTA (5 << 4)
+#define SOS_X86_VIDEO_BG_BROWN (6 << 4)
+#define SOS_X86_VIDEO_BG_LTGRAY (7 << 4)
+/* Blinking */
+#define SOS_X86_VIDEO_FG_BLINKING (1 << 7)
+
+
+/** Setup the video RAM mapping and clear the screen */
+sos_ret_t sos_x86_videomem_setup(void);
+
+/** Clears the screen and set the background color as given by
+ attribute */
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute);
+
+/** Print the string on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str);
+
+/** Print the character on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+ __attribute__ ((format (printf, 4, 5)));
+
+#endif /* _SOS_X86_VIDEOMEM_H_ */
diff --git a/sos-code-article2/extra/Makefile b/sos-code-article2/extra/Makefile
new file mode 100644
index 0000000..f858aa6
--- /dev/null
+++ b/sos-code-article2/extra/Makefile
@@ -0,0 +1,40 @@
+OBJCOPY=objcopy
+
+all: sos_qemu.img
+
+-include ../.mkvars
+
+# The image is the simple concatenation of the boot sector and the kernel
+# It may be use in bochs or on a real floppy, but NOT in qemu (see below)
+sos_bsect.img: bsect.bin sos.bin
+ cat $^ > $@
+ @echo "You can use the $@ image in bochs or on a real floppy (NOT qemu)"
+
+# For qemu, the trick is to tell it we have *more* than 1440 sectors (720kB).
+# Rtherwise the qemu disk geometry will be configured to be that of a 720kB
+# floppy, while our boot sector assumes it to be 1.44MB
+sos_qemu.img: sos_bsect.img
+ # Padding with 0s after the bsect/kernel image
+ cat $< /dev/zero | dd of=$@ bs=1k count=1440
+ @echo "You can use the $@ image in qemu, bochs, or on a real floppy"
+
+# we extract the boot sector from the main ELF binary
+bsect.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -j .bootsect $< $@
+
+# we extract the kernel code from the main ELF binary
+sos.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -R .bootsect $< $@
+
+# The main ELF binary contains the boot sector and the kernel code
+# linked together (hence we deal with a SINGLE image that we split
+# above) because they share some symbol definitions
+sos_bsect.elf: bootsect.o compile_kernel
+ $(LD) --warn-common -T ./sos_bsect.lds -o $@ \
+ bootsect.o $(wildcard ../hwcore/*.o ../drivers/*.o ../sos/*.o)
+
+compile_kernel:
+ $(MAKE) -C ..
+
+clean:
+ $(RM) *.img *.elf *.bin *~ *.o *.out
diff --git a/sos-code-article2/extra/README b/sos-code-article2/extra/README
new file mode 100644
index 0000000..0272f1f
--- /dev/null
+++ b/sos-code-article2/extra/README
@@ -0,0 +1,73 @@
+
+Contents of the extra/ directory
+================================
+
+Data and configuration files to support generation of sos on non-x86
+and/or grub-less hosts:
+ - dot.mkvars: file to copy as .mkvars in the root directory to
+ compile on a non-x86 host, and to generate the grub floppy image on
+ a grub-less host
+ - grub.img.gz: compressed image of a Grub floppy (without any
+ kernel). Used by dot.mkvars.
+ - mtoolsrc: file needed by .mkvars to compile a the floppy image
+
+Support of a sos-specific boot sector:
+ - Makefile: rules to compile sos_bsect.img, the floppy image with the
+ boot sector and the Sos
+ - bootsect.S: x86 Sos boot sector (GNU as). Depends on sos_bsect.lds
+ - sos_bsect.lds: ld script to bind the boot sector with the remaining
+ of the kernel
+
+Misc:
+ - qemu-port-e9.diff: patch over qemu to support the bochs "port 0xe9 hack"
+
+
+What you can do with these files
+================================
+
+
+*** Compile SOS from another architecture:
+------------------------------------------
+ - compile a cross-compiler for the i586-gnu target. This involves
+ compiling the binutils and gcc. Here are example configuration
+ options for them:
+ binutils (replace sparc-cun-solaris with your arch):
+ ../binutils-2.13/configure --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/binutils-2.11 --host=sparc-sun-solaris2.7 i586-gnu
+ make && make install
+ gcc (ditto):
+ CFLAGS="-O2 -Dinhibit_libc" ../gcc-3.2/configure --target=i586-gnu --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/gcc-3.2 --with-as=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/as --with-ld=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/ld --with-gnu-as --with-gnu-ld --enable-languages=c --disable-shared --disable-multilib --disable-nls --enable-threads=single
+ make && make install
+ - compile the mtools
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS from an x86 where grub is not or incorrectly installed:
+--------------------------------------------------------------------------
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS with its own bootloader:
+-------------------------------------------
+ - for cross-architecture compilation: see above
+ - cd to this extra/ directory
+ - run 'make'
+ - the floppy image is: sos_bsect.img
+ NOTE : SOS will not boot correctly this way after article 2 !
+
+
+--
+David Decotigny
diff --git a/sos-code-article2/extra/bootsect.S b/sos-code-article2/extra/bootsect.S
new file mode 100644
index 0000000..f01ca20
--- /dev/null
+++ b/sos-code-article2/extra/bootsect.S
@@ -0,0 +1,393 @@
+
+/*
+ * @(#) $Id: bootsect.S,v 1.6 2004/06/18 07:43:51 d2 Exp $
+ * Description : Bootsecteur en syntaxe AT&T
+ * Auteurs : Thomas Petazzoni & Fabrice Gautier & Emmanuel Marty
+ * Jerome Petazzoni & Bernard Cassagne & coffeeman
+ * David Decotigny
+ * Bug reports to kos-misc@enix.org
+ */
+
+/*
+ * But global de ce bootsecteur :
+ *
+ * - Initialiser la becane
+ * - Charger le kernel
+ * - Passer en mode protege
+ * - Executer le kernel
+ *
+ * Taille restante : Je vous rappelle qu'un bootsecteur ne peut faire
+ * qu'au maximum 512 octets dont 2 octets obligatoires 0xAA55. Sur
+ * les 510 octets reellement utilisables, il reste 3 octets dispo (60
+ * si on decide d'enlever le BPB un jour) !!!
+ *
+ * thomas_petazzoni : - detection des codes d'erreurs de chargement
+ * David_Decotigny : - Passage en GNU as
+ * David_Decotigny : - Chargement du noyau au-dela du 1er Mega (taille
+ * max = 0x9e000 octets = 632ko), pour avoir le
+ * meme noyau sous grub et avec le bootsecteur
+ */
+
+ /*
+ * Sequence d'operations :
+ * - Le BIOS charge le bootsect en 0x7c00 (BOOT_ADRESS). On choisit
+ * la representation 0x7c0:0000 pour que le .org 0 reste valide
+ * - Le bootsect se deplace de lui-meme en 0x9f000 (COPY_ADRESS). On
+ * choisit la representation 0x9f00:0000 pour que le .org 0 reste
+ * valide
+ * - Le bootsect verifie que le processeur est du type 386+
+ * - Il charge le noyau depuis la disquette en memoire a partir de
+ * 0x1000 (LOAD_ADRESS). Le noyau peut au max tenir sur
+ * SECTORS_TO_LOAD secteurs
+ * - Il passe en pmode flat (apres ouverture a20)
+ * - Il recopie le noyau (situe en LOAD_ADRESS) vers son adresse
+ * finale (FINAL_ADDRESS = 2Mo). La recopie se fait sur tout l'espace
+ * LOAD_ADRESS ---> COPY_ADRESS, c'est a dire sur 0x9e000 octets =
+ * 632ko. Le noyau peut donc au max faire 632ko. Le nombre max de
+ * secteurs de disquette qu'on peut charger est donc 1264
+ */
+
+
+/* La taille de la pile */
+#define BOOT_STACK_SIZE 0x4000
+
+ .file "bootsect.S"
+
+ /* Tout est place dans une seule section */
+ .section ".bootsect"
+
+ /* L'essentiel du bootsector (sauf les 1eres instructions)
+ sont a un offset 0. On fait en sorte que le compilo soit
+ d'accord la-dessus. Quand on a des adresse realm exotiques
+ (0x7c00, 0x9f000, ...), on s'arrange toujours pour avoir un
+ offset de 0 => on choisira le segment adapte (0x7c0,
+ 0x9f00, ...). Il ne faut pas oublier le ld -Ttext 0 */
+ .org 0
+
+ /* Pour que gas genere du 16bits, afin que ca marche en realm */
+ .code16
+
+#define SECTORS_TO_LOAD 128 /* 64 ko */ /* MAX=1264 */
+
+/*
+ * Parametres de la disquette. Comme c'est chiant de faire une
+ * procedure de detection auto, et que ca prend de la place, on fait
+ * ca "a la main". Par exemple, une DD 720 Ko a 9 secteurs/piste, une
+ * 1.44 Mo a 18 secteurs/pistes
+ */
+#define CYLS 80
+#define HEADS 1
+#define SECTS 18
+
+#define BOOT_ADRESS 0x07C00 /* Adresse de demarrage (lineaire) */
+#define BOOT_SEG (BOOT_ADRESS>>4) /* Segment de Boot */
+#define BOOT_SIZE 512 /* Taille bu bootsecteur */
+#define COPY_ADRESS 0x9F000 /* La ou on va copier le
+ bootsecteur (lineaire) */
+#define COPY_SEG (COPY_ADRESS>>4) /* Segment de la ou on va
+ copier le bootsecteur */
+#define LOAD_ADRESS 0x01000 /* 1er chargement du systeme */
+#define LOAD_SEG (LOAD_ADRESS>>4) /* Segment du 1er chargement du */
+#define MAX_KERN_LEN COPY_ADRESS-LOAD_ADRESS /* Taille noyau maxi */
+
+/* IMPORTANT : Cette valeur DOIT etre identique a l'adresse presente
+ dans sos.lds ! */
+#define FINAL_ADDRESS 0x200000 /* Adresse finale (physique de 0 a 4G)
+ ou est charge le noyau */
+
+#define OP16 .byte 0x66 ;
+#define OP32 .byte 0x66 ;
+
+/*
+ * Procedure qui vide le buffer clavier.
+ */
+#define WAITKB \
+ 1: ;\
+ .word 0xeb ;\
+ .word 0xeb ;\
+ inb $0x64, %al ;\
+ andb $0x2, %al ;\
+ jnz 1b
+
+ /* Le point d'entree dans le bootsect */
+.globl _bsect
+_bsect:
+
+ /*
+ * La portion qui suit est situee a un offset 0x7c00 en
+ * memoire. Attention donc aux references memoire dans cette
+ * partie. On choisit de rester en offset 0 (.org 0), mais on
+ * charge correctement les segments a 0x7c0.
+ */
+
+ movw $BOOT_SEG, %ax /* le bootsecteur est a 0x7C00 en lineaire */
+ movw %ax, %ds /* on le copie a l'adresse COPY_ADRESS */
+ xorw %si, %si /* comme cette adresse est la plus haute de la mem */
+ xorw %di, %di /* on pourra charger un kernel + gros */
+ movw $(BOOT_SIZE>>1), %cx
+ movw $COPY_SEG, %ax
+ movw %ax, %es
+ cld
+ rep ; movsw
+
+ /* on continue a executer le bootsecteur, mais maintenant a
+ partir de 0x9F000, qu'on represente sous la forme
+ 0x9f00:offset */
+ ljmp $COPY_SEG, $here
+
+ /*
+ * A partir de maintenant, on est a un offset 0 en memoire
+ * (segment 0x9f00), conformement a ce que veut le compilo.
+ */
+here:
+ movw %ax, %ds
+
+ /* Petite pile temporaire (1k - 3.84k en RAM ; les adresses 0-1k
+ correspondent au vecteur d'interruptions). */
+ movw %ax, %ss
+ movw $(LOAD_ADRESS - 0x10), %sp
+
+ /* Efface l'ecran */
+ movb $0x0, %ah
+ movb $0x3, %al
+ int $0x10
+
+ /* Affiche les messages d'attente */
+ movw $loadkern, %si
+ call message
+ movw $check, %si
+ call message
+
+check386:
+ /*
+ * la attention, plus complexe : on teste si le proc est un
+ * 386+ pour cela, on va essayer de modifier les bits 12 ? 14
+ * du registre E-flag si la modification reste, alors le proc
+ * est un 386+, sinon, c'est =< 286
+ *
+ * Merci a Emmanuel Marty pour la compatibilite avec les 386
+ * "pre-jurassique"
+ */
+
+ pushf /* on sauvegarde le E-Flag */
+ movb $0x70, %ah
+ pushw %ax
+ popf
+ pushf
+ popw %ax
+ orb %ah, %ah
+ je no386 /* si la modif n'est pas valable, alors on saute a
+ no386 */
+ popf /* on les restaure ? la fin ... */
+
+ /* Message de confirmation de 386+ et d'attente */
+ movw $found386, %si
+ call message
+ movw $loading, %si
+ call message
+
+/* Copie du noyau disquette => RAM a partir de 0x1000
+ L'adresse de destination est définie par es:0, où es vaut
+ initialement 0x100 (ie correspond alors à l'adresse 256*16, soit 4
+ ko). Chaque itération incrémente ce registre es de 32, ce qui
+ correspond à un bond de 32*16 en mémoire, soit la taille d'un
+ secteur. De cette façon, puisqu'on joue sur les segments plutôt que
+ sur les offsets, la taille du noyau n'est pas limitée à 64 ko. Elle
+ est limitée par contre à la taille de la mémoire disponible sous
+ les 1Mo, \ie 640 ko (0x9f000 - 0x1000). */
+copyKernel:
+ /* Chargement du noyau en LOAD_SEG:0 */
+ /* 3 iterateurs :
+ - load_size : le nbre de secteurs a charger
+ - cl : le secteur ou on en est pour le
+ cylindre en cours (<= SECTS)
+ - dh : la tete en cours (0/1)
+ */
+ movb $0, %dl
+ movw $LOAD_SEG, %ax
+ movw %ax, %es
+
+ xorw %bx, %bx
+ xorw %dx, %dx
+ movw $1, %cx /* premier secteur */
+
+.nextsector: /* prochain secteur */
+ incb %cl /* en incrementant CL */
+ cmpb $SECTS, %cl /* si CL =< SECTS (=nbre de secteurs/pistes)
+ alors on charge */
+ jbe .sector
+ movb $1, %cl /* sinon on revient au secteur 1 */
+ incb %dh /* mais sur l'autre tete */
+ cmpb $1, %dh /* on recompare, si DH =< 1 */
+ je .sector /* on charge */
+ movb $0, %dh /* sinon on repasse a la tete 0 */
+ incb %ch /* mais on change de cylindre */
+
+.sector:
+ pushw %es
+ movw $0x0201, %ax /* service 0x2, chargement 0x1 seecteur */
+ int $0x13 /* Go ! */
+ jc halt /* erreur */
+ popw %ax
+ addw $32, %ax /* on a charge un secteur, donc on doit
+ charger 512 bytes plus loin */
+ movw %ax, %es /* on avance donc le segment du buffer de
+ 32bytes, ie 1 secteur en RAM (car 32*16=512) */
+
+ movw $(0x0E*256+'.'), %ax /* affiche un point */
+ int $0x10
+
+ decw (load_size) /* et on repart pour le prochain secteur
+ tant qu'on n'a pas fini ! */
+ jnz .nextsector
+
+after:
+ movw $0x03f2, %dx
+ inb %dx, %al /* stoppe le moteur */
+ andb $0x0f, %al
+ outb %al, %dx
+
+ cli /* on interdit les interruptions */
+
+fincopie:
+ pushw %cs
+ popw %ds
+
+ /* on ouvre la porte A20 */
+ WAITKB /* on vide le buffer */
+ movb $0xd1, %al /* on met a jour le port */
+ outb %al, $0x64
+ WAITKB
+ movb $0xdf, %al /* bit 2 = ouverture/fermeture */
+ outb %al, $0x60
+
+ /*
+ * init gdt
+ */
+InitGDT:
+ /* Préparation du flat mode */
+ lgdt gdtr
+
+GoPMode:
+ /* Passage en mode protégé */
+ movl %cr0, %eax
+ orb $1, %al /* set PE bit to 1 */
+ movl %eax, %cr0
+
+ /* we are not yet in Pmode jump 'in' pmode clearing prefetch
+ * queue and loading a new selector */
+ movw $0x10, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+/*
+ * Code 32 bits ============================================================
+ */
+ .code32
+
+JumpToHere32: /* Se deplace a l'endroit actuel, en passant en 32bits
+ et en utilisant la gdt, et vide la prefetch queue */
+ .byte 0x66 /* Prefixe 32bits : en realite, jusqu'au jmp, on est
+ encore en 16 bits */
+ ljmp $0x8, $(COPY_ADRESS+(Here32))
+Here32:
+ /* Et voila : On est en 32 bits vrai */
+
+MoveKernelToFinalAddr: /* Deplace le noyau (en LOAD_ADDRESS) vers sa
+ destination finale (FINAL_ADDRESS) */
+ movl $0x10, %eax
+ movl %eax, %ds /* Seg Src = DSeg */
+ movl %eax, %es /* Sed Dest = DSeg */
+ cld
+ movl $LOAD_ADRESS, %esi /* On commence la copie au debut du noyau */
+ movl $FINAL_ADDRESS, %edi /* On copie vers cette adresse */
+ movl $MAX_KERN_LEN, %ecx /* Taille recopie */
+ shrl $2, %ecx
+ rep
+ movsl
+
+LaunchKernel:
+ /* Met en place une pile au niveau du symbole "stack" */
+ movl %eax, %ss
+ movl $(stack + BOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Saut vers le noyau. La GDT est en place (flat mode), les
+ * selecteurs aussi, a20 est ouverte, et les interruptions sont
+ * cli + pas de idt. Le PIC n'est pas programme */
+ ljmp $0x8, $sos_main
+
+/*
+ * Utilities ============================================================
+ */
+ .code16
+
+message:
+ lodsb /* charge ds:si dans al et incremente si */
+ orb %al, %al /* si al = 0 */
+ jz 1f
+ movb $0x0e, %ah /* service 0Eh (affichage d'un caractere) */
+ movw $0x0007, %bx /* Parametres : blanc sur fond noir */
+ int $0x10 /* Appel de l'interruption 10h */
+ jmp message /* On repart au début ... */
+ 1: ret /* si la chaine est finie alors on retourne
+ dans la fonction appelante */
+
+halt:
+ pushw %cs
+ popw %es
+ movw $haltmsg, %si
+ call message
+ cli
+ 1: jmp 1b
+ ret
+
+no386:
+ movw $need386, %si
+ call message
+ call halt
+
+ /*
+ * GDT
+ */
+
+gdt:
+gdtr:
+NULL_Desc:
+ .word (EndGDT)-(gdt)-1 /* Taille GDT */
+ .long (gdt)+COPY_ADRESS
+unused:
+ .word 0
+
+CS_Desc: /* 0x8 */
+ .word 0xFFFF, 0
+ .byte 0, 0x9B, 0xCF, 0
+
+DS_Desc: /* 0x10 */
+ .word 0xFFFF, 0
+ .byte 0, 0x93, 0xCF, 0
+
+EndGDT:
+
+ /* quelques messages */
+
+loadkern: .string "-= S O S =- : The Simple Operating System \r\n"
+check: .string "Checking for a 386+ processor... "
+found386: .string " [OK]\r\n"
+need386: .string " [FAILED]\r\n"
+diskerror: .string "Disk Error\r\n"
+loading: .string "Loading... "
+haltmsg: .string "System Halted\r\n"
+
+/*** Les code/données du boot secteur se terminent ICI. le marqueur de
+ * fin (aa55) est ajouté automatiquement par le script ld
+ * sos_bsect.lds ***/
+
+/* La pile de 16k qu'on utilise au niveau de LaunchKernel se trouve
+ declaree avec le noyau, dans sa section ".bss", cad HORS du boot
+ secteur ! (sinon ca depasserait 512B, forcément). On aurait pu la
+ définir directement dans le sos_bsect.lds, ou dans un fichier .c
+ auxiliaire pour plus de clarté */
+.comm stack, BOOT_STACK_SIZE
diff --git a/sos-code-article2/extra/dot.mkvars b/sos-code-article2/extra/dot.mkvars
new file mode 100644
index 0000000..1f7dca5
--- /dev/null
+++ b/sos-code-article2/extra/dot.mkvars
@@ -0,0 +1,29 @@
+# For cross-compilation and/or installations without grub available,
+# copy this file as .mkvars to the root directory of the SOS sources,
+# and customize the CC/LD/... variables. You still need the mtools
+# installed and running
+
+CC := i586-gnu-gcc
+LD := i586-gnu-ld
+OBJCOPY := i586-gnu-objcopy
+CFLAGS += -O3
+
+# Configuration of mtools
+MTOOLSRC = extra/mtoolsrc
+export MTOOLSRC
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ) menu.txt
+ gzip -dc < extra/grub.img.gz > $@
+ mcopy menu.txt v:/boot/grub/
+ mmd v:/system
+ mcopy sos.elf v:/system/sos.elf
+
+menu.txt:
+ echo timeout 0 > $@
+ echo default 0 >> $@
+ echo title SOS >> $@
+ echo "root (fd0)" >> $@
+ echo kernel /system/sos.elf >> $@
+
+runbochs: all
+ echo c | bochs -q
diff --git a/sos-code-article2/extra/grub.img.gz b/sos-code-article2/extra/grub.img.gz
new file mode 100644
index 0000000..4f98e74
--- /dev/null
+++ b/sos-code-article2/extra/grub.img.gz
Binary files differ
diff --git a/sos-code-article2/extra/mtoolsrc b/sos-code-article2/extra/mtoolsrc
new file mode 100644
index 0000000..df1a26e
--- /dev/null
+++ b/sos-code-article2/extra/mtoolsrc
@@ -0,0 +1,2 @@
+# For older versions of mtools, you may have to remove "filter"
+drive v: file="fd.img" 1.44M filter
diff --git a/sos-code-article2/extra/qemu-port-e9.diff b/sos-code-article2/extra/qemu-port-e9.diff
new file mode 100644
index 0000000..d8be044
--- /dev/null
+++ b/sos-code-article2/extra/qemu-port-e9.diff
@@ -0,0 +1,73 @@
+--- Makefile.target 17 Mar 2004 23:46:04 -0000 1.19
++++ Makefile.target 18 Mar 2004 14:20:29 -0000
+@@ -217,7 +217,8 @@
+ # must use static linking to avoid leaving stuff in virtual address space
+ VL_OBJS=vl.o osdep.o block.o monitor.o \
+ ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
+- fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
++ fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o \
++ port-e9.o
+ ifeq ($(TARGET_ARCH), ppc)
+ VL_OBJS+= hw.o
+ endif
+--- hw/pc.c 14 Mar 2004 21:46:48 -0000 1.2
++++ hw/pc.c 18 Mar 2004 14:20:29 -0000
+@@ -371,6 +371,7 @@
+ SB16_init();
+
+ fdctrl_init(6, 2, 0, 0x3f0, fd_table);
++ port_e9_init();
+
+ cmos_init(ram_size, boot_device);
+ }
+--- /dev/null 2003-01-30 11:24:37.000000000 +0100
++++ port-e9.c 2004-03-18 15:18:52.660493187 +0100
+@@ -0,0 +1,38 @@
++/*
++ * QEMU Port 0xe9 hack
++ *
++ * Copyright (c) 2000-2004 E. Marty, the bochs team, D. Decotigny
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++ * THE SOFTWARE.
++ */
++#include <stdio.h>
++#include <unistd.h>
++#include <inttypes.h>
++
++#include "vl.h"
++
++static void bochs_e9_write(void *opaque, uint32_t address, uint32_t data)
++{
++ write(fileno(stdout), &data, 1);
++}
++
++void port_e9_init ()
++{
++ register_ioport_write(0xe9, 1, 1, bochs_e9_write, NULL);
++}
+--- vl.h 17 Mar 2004 23:17:16 -0000 1.14
++++ vl.h 18 Mar 2004 14:29:06 -0000
+@@ -268,4 +268,7 @@
+ void term_flush(void);
+ void term_print_help(void);
+
++/* port-e9.c */
++void port_e9_init(void);
++
+ #endif /* VL_H */
diff --git a/sos-code-article2/extra/sos_bsect.lds b/sos-code-article2/extra/sos_bsect.lds
new file mode 100644
index 0000000..ac42f23
--- /dev/null
+++ b/sos-code-article2/extra/sos_bsect.lds
@@ -0,0 +1,61 @@
+/* Copyright (C) 2004, David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+SECTIONS
+{
+ /* ***********************************************
+ * The bootsector is here. We link it against the remaining of the kernel
+ * in order to automatically figure out its size that must be loaded
+ * from file to memory (see the load_size definition below)
+ */
+
+ /* If we use one, we put the boot sector here. We don't set its
+ * address to 0x7c000 (aka 0x7c00:0), since it reloads itself to
+ * 0x9f000, causing the 0x7c000 address to be meaningless too. So we
+ * chose to pretend that the address is 0x0, and to make a little
+ * address arithmetic in bootsect.S */
+ .bootsect 0x0 :
+ {
+ /* The code for the boot sector goes here */
+ *(.bootsect);
+
+ /* The load_size symbol contains the size of the area (in
+ * sectors, aka 512 Bytes) that the boot sector should copy from
+ * the disk. The bss section is not included since it uses 0
+ * bytes on disk */
+ load_size = .;
+ LONG((__e_load - __b_load + 511) >> 9);
+ /* ---> This is equivalent to ceil( (__e_load - __b_load) / 512 ) */
+
+ /* At offsets 511 and 512, we set the boot sector signature (AA55h) */
+ . = 0x1fe;
+ SHORT(0xAA55);
+ }
+}
+
+
+/* This is to avoid a cut/paste here. Please notice that a multiboot
+ * section WILL be inserted, which is NOT mandatory (we could have
+ * removed it without getting into trouble). Please note however that
+ * the *.bin files will NOT be multiboot compatible (they are not in ELF
+ * format): they are expected to be directly booted by the BIOS (or
+ * by the "chainloader" command of Grub). */
+INCLUDE ../support/sos.lds
+
+/* We overload the entry set in sos.lds, just to avoid an ld warning */
+ENTRY(sos_main);
diff --git a/sos-code-article2/hwcore/exception.c b/sos-code-article2/hwcore/exception.c
new file mode 100644
index 0000000..9ab5aff
--- /dev/null
+++ b/sos-code-article2/hwcore/exception.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "idt.h"
+#include "irq.h"
+
+#include "exception.h"
+
+/* array of exception wrappers, defined in exception_wrappers.S */
+extern sos_vaddr_t sos_exception_wrapper_array[SOS_EXCEPT_NUM];
+
+/* arrays of exception handlers, shared with exception_wrappers.S */
+sos_exception_handler_t sos_exception_handler_array[SOS_EXCEPT_NUM] =
+ { NULL, };
+
+sos_ret_t sos_exceptions_setup(void)
+{
+ /* We inidicate that the double fault exception handler is defined,
+ and give its address. this handler is a do-nothing handler (see
+ exception_wrappers.S), and it can NOT be overriden by the
+ functions below */
+ return sos_idt_set_handler(SOS_EXCEPT_BASE + SOS_EXCEPT_DOUBLE_FAULT,
+ (sos_vaddr_t) sos_exception_wrapper_array[SOS_EXCEPT_DOUBLE_FAULT],
+ 0 /* CPL0 routine */);
+}
+
+
+sos_ret_t sos_exception_set_routine(int exception_number,
+ sos_exception_handler_t routine)
+{
+ sos_ret_t retval;
+ sos_ui32_t flags;
+
+ if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM))
+ return -SOS_EINVAL;
+
+ /* Double fault not supported */
+ if (exception_number == SOS_EXCEPT_DOUBLE_FAULT)
+ return -SOS_ENOSUP;
+
+ sos_disable_IRQs(flags);
+
+ retval = SOS_OK;
+
+ /* Set the exception routine to be called by the exception wrapper */
+ sos_exception_handler_array[exception_number] = routine;
+
+ /* If the exception is to be enabled, update the IDT with the exception
+ wrapper */
+ if (routine != NULL)
+ retval
+ = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number,
+ (sos_vaddr_t) sos_exception_wrapper_array[exception_number],
+ 0 /* CPL0 routine */);
+ else /* Disable the IDT entry */
+ retval
+ = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number,
+ (sos_vaddr_t)NULL /* No routine => disable IDTE */,
+ 0 /* don't care */);
+
+ sos_restore_IRQs(flags);
+ return retval;
+}
+
+
+sos_exception_handler_t sos_exception_get_routine(int exception_number)
+{
+ if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM))
+ return NULL;
+
+ /* Double fault not supported */
+ if (exception_number == SOS_EXCEPT_DOUBLE_FAULT)
+ return NULL;
+
+ /* Expected to be atomic */
+ return sos_exception_handler_array[exception_number];
+}
diff --git a/sos-code-article2/hwcore/exception.h b/sos-code-article2/hwcore/exception.h
new file mode 100644
index 0000000..7e52fe5
--- /dev/null
+++ b/sos-code-article2/hwcore/exception.h
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWEXCEPT_H_
+#define _SOS_HWEXCEPT_H_
+
+/**
+ * @file exception.c
+ *
+ * Hardware exception routines management.
+ */
+
+#ifndef ASM_SOURCE
+# include <sos/errno.h>
+#endif
+
+/**
+ * Standard Intel x86 exceptions.
+ *
+ * @see Intel x86 doc vol 3, section 5.12.
+ */
+#define SOS_EXCEPT_DIVIDE_ERROR 0 // No error code
+#define SOS_EXCEPT_DEBUG 1 // No error code
+#define SOS_EXCEPT_NMI_INTERRUPT 2 // No error code
+#define SOS_EXCEPT_BREAKPOINT 3 // No error code
+#define SOS_EXCEPT_OVERFLOW 4 // No error code
+#define SOS_EXCEPT_BOUND_RANGE_EXCEDEED 5 // No error code
+#define SOS_EXCEPT_INVALID_OPCODE 6 // No error code
+#define SOS_EXCEPT_DEVICE_NOT_AVAILABLE 7 // No error code
+#define SOS_EXCEPT_DOUBLE_FAULT 8 // Yes (Zero)
+#define SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN 9 // No error code
+#define SOS_EXCEPT_INVALID_TSS 10 // Yes
+#define SOS_EXCEPT_SEGMENT_NOT_PRESENT 11 // Yes
+#define SOS_EXCEPT_STACK_SEGMENT_FAULT 12 // Yes
+#define SOS_EXCEPT_GENERAL_PROTECTION 13 // Yes
+#define SOS_EXCEPT_PAGE_FAULT 14 // Yes
+#define SOS_EXCEPT_INTEL_RESERVED_1 15 // No
+#define SOS_EXCEPT_FLOATING_POINT_ERROR 16 // No
+#define SOS_EXCEPT_ALIGNEMENT_CHECK 17 // Yes (Zero)
+#define SOS_EXCEPT_MACHINE_CHECK 18 // No
+#define SOS_EXCEPT_INTEL_RESERVED_2 19 // No
+#define SOS_EXCEPT_INTEL_RESERVED_3 20 // No
+#define SOS_EXCEPT_INTEL_RESERVED_4 21 // No
+#define SOS_EXCEPT_INTEL_RESERVED_5 22 // No
+#define SOS_EXCEPT_INTEL_RESERVED_6 23 // No
+#define SOS_EXCEPT_INTEL_RESERVED_7 24 // No
+#define SOS_EXCEPT_INTEL_RESERVED_8 25 // No
+#define SOS_EXCEPT_INTEL_RESERVED_9 26 // No
+#define SOS_EXCEPT_INTEL_RESERVED_10 27 // No
+#define SOS_EXCEPT_INTEL_RESERVED_11 28 // No
+#define SOS_EXCEPT_INTEL_RESERVED_12 29 // No
+#define SOS_EXCEPT_INTEL_RESERVED_13 30 // No
+#define SOS_EXCEPT_INTEL_RESERVED_14 31 // No
+
+#ifndef ASM_SOURCE
+
+typedef void (*sos_exception_handler_t)(int exception_number);
+
+sos_ret_t sos_exceptions_setup(void);
+sos_ret_t sos_exception_set_routine(int exception_number,
+ sos_exception_handler_t routine);
+sos_exception_handler_t sos_exception_get_routine(int exception_number);
+#endif /* ! ASM_SOURCE */
+
+#endif /* _SOS_HWEXCEPT_H_ */
diff --git a/sos-code-article2/hwcore/exception_wrappers.S b/sos-code-article2/hwcore/exception_wrappers.S
new file mode 100644
index 0000000..2f7665c
--- /dev/null
+++ b/sos-code-article2/hwcore/exception_wrappers.S
@@ -0,0 +1,197 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "exception.h"
+
+.file "exception_wrappers.S"
+
+.text
+
+/* The address of the table of handlers (defined in exception.c) */
+.extern sos_exception_handler_array
+
+/* The address of the table of wrappers (defined below, and shared
+ with exception.c */
+.globl sos_exception_wrapper_array
+
+
+/**
+ * For exceptions with/without error code, refer to Intel x86 doc vol 3,
+ * section 5.12
+ */
+
+/* These wrappers are for exceptions without error code */
+.irp id, \
+ SOS_EXCEPT_DIVIDE_ERROR, \
+ SOS_EXCEPT_DEBUG, \
+ SOS_EXCEPT_NMI_INTERRUPT, \
+ SOS_EXCEPT_BREAKPOINT, \
+ SOS_EXCEPT_OVERFLOW, \
+ SOS_EXCEPT_BOUND_RANGE_EXCEDEED, \
+ SOS_EXCEPT_INVALID_OPCODE, \
+ SOS_EXCEPT_DEVICE_NOT_AVAILABLE, \
+ SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN, \
+ SOS_EXCEPT_INTEL_RESERVED_1, \
+ SOS_EXCEPT_FLOATING_POINT_ERROR, \
+ SOS_EXCEPT_MACHINE_CHECK, \
+ SOS_EXCEPT_INTEL_RESERVED_2, \
+ SOS_EXCEPT_INTEL_RESERVED_3, \
+ SOS_EXCEPT_INTEL_RESERVED_4, \
+ SOS_EXCEPT_INTEL_RESERVED_5, \
+ SOS_EXCEPT_INTEL_RESERVED_6, \
+ SOS_EXCEPT_INTEL_RESERVED_7, \
+ SOS_EXCEPT_INTEL_RESERVED_8, \
+ SOS_EXCEPT_INTEL_RESERVED_9, \
+ SOS_EXCEPT_INTEL_RESERVED_10, \
+ SOS_EXCEPT_INTEL_RESERVED_11, \
+ SOS_EXCEPT_INTEL_RESERVED_12, \
+ SOS_EXCEPT_INTEL_RESERVED_13, \
+ SOS_EXCEPT_INTEL_RESERVED_14
+
+ .p2align 2, 0x90
+ sos_exception_wrapper_\id:
+ .type sos_exception_wrapper_\id,@function
+
+ /* Fake error code */
+ pushl $0
+ /* Backup the context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Call the handler with exception number as
+ * argument */
+ pushl $\id
+ leal sos_exception_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+
+ popl %ebp
+ /* Remove fake error code */
+ addl $4, %esp
+ iret
+.endr
+
+ /* These wrappers are for exceptions with error code */
+.irp id, \
+ SOS_EXCEPT_INVALID_TSS, \
+ SOS_EXCEPT_SEGMENT_NOT_PRESENT, \
+ SOS_EXCEPT_STACK_SEGMENT_FAULT, \
+ SOS_EXCEPT_GENERAL_PROTECTION, \
+ SOS_EXCEPT_PAGE_FAULT, \
+ SOS_EXCEPT_ALIGNEMENT_CHECK
+
+ .p2align 2, 0x90
+ sos_exception_wrapper_\id:
+ .type sos_exception_wrapper_\id,@function
+
+ /* ret eflags */
+ /* ret cs */
+ /* ret eip */
+ /* Error code */
+
+ /* Backup the context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Call the handler with exception number as
+ * argument */
+ pushl $\id
+ leal sos_exception_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Error code isn't compatible with iretd */
+ addl $4, %esp
+
+ iret
+.endr
+
+
+/* Double fault handler not supported. We must define it since we
+ define an entry for it in the sos_exception_wrapper_array. */
+.irp id, SOS_EXCEPT_DOUBLE_FAULT
+.p2align 2, 0x90
+sos_exception_wrapper_\id:
+.type sos_exception_wrapper_\id,@function
+1: hlt
+ jmp 1b /* Machine halting */
+.endr
+
+/* Build the sos_irq_wrapper_array, shared with interrupt.c */
+.section ".rodata"
+.p2align 5, 0x0
+sos_exception_wrapper_array:
+ .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
+ 16,17,18,19,20,21,22,23,24,25,26,27,29,30,31
+ .long (sos_exception_wrapper_\id)
+ .endr
diff --git a/sos-code-article2/hwcore/gdt.c b/sos-code-article2/hwcore/gdt.c
new file mode 100644
index 0000000..7945c8c
--- /dev/null
+++ b/sos-code-article2/hwcore/gdt.c
@@ -0,0 +1,150 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "segment.h"
+
+#include "gdt.h"
+
+
+/**
+ * The sructure of a segment descriptor.
+ *
+ * @see Intel x86 doc, Vol 3, section 3.4.3, figure 3-8. For segment
+ * types, see section 3.5
+ */
+struct x86_segment_descriptor
+{
+ /* Lowest dword */
+ sos_ui16_t limit_15_0; /* Segment limit, bits 15..0 */
+ sos_ui16_t base_paged_addr_15_0; /* Base address, bits 15..0 */
+
+ /* Highest dword */
+ sos_ui8_t base_paged_addr_23_16; /* Base address bits 23..16 */
+ sos_ui8_t segment_type:4; /* Section 3.4.3.1 (code/data)
+ and 3.5 (system) of Intel x86 vol 3 */
+ sos_ui8_t descriptor_type:1; /* 0=system, 1=Code/Data */
+ sos_ui8_t dpl:2;
+ sos_ui8_t present:1;
+
+ sos_ui8_t limit_19_16:4; /* Segment limit, bits 19..16 */
+ sos_ui8_t custom:1;
+ sos_ui8_t zero:1;
+ sos_ui8_t op_size:1; /* 0=16bits instructions, 1=32bits */
+ sos_ui8_t granularity:1; /* 0=limit in bytes, 1=limit in pages */
+
+ sos_ui8_t base_paged_addr_31_24; /* Base address bits 31..24 */
+} __attribute__ ((packed, aligned (8)));
+
+
+/**
+ * The GDT register, which stores the address and size of the
+ * GDT.
+ *
+ * @see Intel x86 doc vol 3, section 2.4, figure 2-4; and section
+ * 3.5.1
+ */
+struct x86_gdt_register {
+ /* The maximum GDT offset allowed to access an entry in the GDT */
+ sos_ui16_t limit;
+
+ /* This is not exactly a "virtual" address, ie an adddress such as
+ those of instructions and data; this is a "linear" address, ie an
+ address in the paged memory. However, in SOS we configure the
+ segmented memory as a "flat" space: the 0-4GB segment-based (ie
+ "virtual") addresses directly map to the 0-4GB paged memory (ie
+ "linear"), so that the "linear" addresses are numerically equal
+ to the "virtual" addresses: this base_addr will thus be the same
+ as the address of the gdt array */
+ sos_ui32_t base_addr;
+} __attribute__((packed, aligned(8)));
+
+
+/**
+ * Helper macro that builds a Segment descriptor for the virtual
+ * 0..4GB addresses to be mapped to the linear 0..4GB linear
+ * addresses.
+ */
+#define BUILD_GDTE(descr_privilege_level,is_code) \
+ ((struct x86_segment_descriptor) { \
+ .limit_15_0= 0xffff, \
+ .base_paged_addr_15_0= 0, \
+ .base_paged_addr_23_16= 0, \
+ .segment_type= ((is_code)?0xb:0x3), \
+ /* With descriptor_type (below) = 1 (code/data), \
+ * see Figure 3-1 of section 3.4.3.1 in Intel \
+ * x86 vol 3: \
+ * - Code (bit 3 = 1): \
+ * bit 0: 1=Accessed \
+ * bit 1: 1=Readable \
+ * bit 2: 0=Non-Conforming \
+ * - Data (bit 3 = 0): \
+ * bit 0: 1=Accessed \
+ * bit 1: 1=Writable \
+ * bit 2: 0=Expand up (stack-related) \
+ * For Conforming/non conforming segments, see \
+ * Intel x86 Vol 3 section 4.8.1.1 \
+ */ \
+ .descriptor_type= 1, /* 1=Code/Data */ \
+ .dpl= ((descr_privilege_level) & 0x3), \
+ .present= 1, \
+ .limit_19_16= 0xf, \
+ .custom= 0, \
+ .op_size= 1, /* 32 bits instr/data */ \
+ .granularity= 1 /* limit is in 4kB Pages */ \
+ })
+
+
+/** The actual GDT */
+static struct x86_segment_descriptor gdt[] = {
+ [SOS_SEG_NULL] = (struct x86_segment_descriptor){ 0, },
+ [SOS_SEG_KCODE] = BUILD_GDTE(0, 1),
+ [SOS_SEG_KDATA] = BUILD_GDTE(0, 0),
+};
+
+sos_ret_t sos_gdt_setup(void)
+{
+ struct x86_gdt_register gdtr;
+
+ /* Address of the GDT */
+ gdtr.base_addr = (sos_ui32_t) gdt;
+
+ /* The limit is the maximum offset in bytes from the base address of
+ the GDT */
+ gdtr.limit = sizeof(gdt) - 1;
+
+ /* Commit the GDT into the CPU, and update the segment
+ registers. The CS register may only be updated with a long jump
+ to an absolute address in the given segment (see Intel x86 doc
+ vol 3, section 4.8.1). */
+ asm volatile ("lgdt %0 \n\
+ ljmp %1,$1f \n\
+ 1: \n\
+ movw %2, %%ax \n\
+ movw %%ax, %%ss \n\
+ movw %%ax, %%ds \n\
+ movw %%ax, %%es \n\
+ movw %%ax, %%fs \n\
+ movw %%ax, %%gs"
+ :
+ :"m"(gdtr),
+ "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE)),
+ "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA))
+ :"memory","eax");
+
+ return SOS_OK;
+}
diff --git a/sos-code-article2/hwcore/gdt.h b/sos-code-article2/hwcore/gdt.h
new file mode 100644
index 0000000..b7e3f4c
--- /dev/null
+++ b/sos-code-article2/hwcore/gdt.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_GDT_H_
+#define _SOS_GDT_H_
+
+/**
+ * @file gdt.h
+ *
+ * The routines that manage the GDT, the table that maps the virtual
+ * addresses (data/instructions, segment-relative), to "linear"
+ * addresses (ie paged-memory). In SOS/x86, we use a "flat" virtual
+ * space, ie the virtual and linear spaces are equivalent.
+ *
+ * @see Intel x86 doc vol 3, chapter 3
+ */
+
+#include <sos/errno.h>
+
+/**
+ * Configure the virtual space as a direct mapping to the linear
+ * address space (ie "flat" virtual space).
+ */
+sos_ret_t sos_gdt_setup(void);
+
+#endif /* _SOS_GDT_H_ */
diff --git a/sos-code-article2/hwcore/i8254.c b/sos-code-article2/hwcore/i8254.c
new file mode 100644
index 0000000..5fbb156
--- /dev/null
+++ b/sos-code-article2/hwcore/i8254.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <hwcore/ioports.h>
+
+#include "i8254.h"
+
+/** 82c54 clock frequency */
+#define I8254_MAX_FREQ 1193180
+
+/* Ports to communicate with the 82c54 */
+#define I8254_TIMER0 0x40
+#define I8254_TIMER1 0x41
+#define I8254_TIMER2 0x42
+#define I8254_CONTROL 0x43
+
+/**
+ * Configure the first timer of the 82c54 chip as a rate generator,
+ * which will raise an IRQ0 on a regular periodic basis, as given by
+ * the freq parameter. Second (RAM refresh) and third (speaker) timers
+ * are left unchanged. Maximum frequency is that of the 8254 clock, ie
+ * 1193180 Hz.
+ *
+ * Ahhh PC systems are nice toys: this maximum "strange" frequency
+ * equals that of the NTSC clock (14.31818 MHz) divided by 12. In
+ * turn, the famous 4.77 MHz cpu clock frequency of the first IBM PC
+ * is this same NTSC frequency divided by 3. Why the NTSC frequency as
+ * a base "standard" ? Because the 14.31818 MHz quartz were cheap at
+ * that time, and because it allows to simply drive altogether the
+ * cpu, the "time of day" timer, and the video signal generators.
+ */
+sos_ret_t sos_i8254_set_frequency(unsigned int freq)
+{
+ unsigned int nb_tick;
+
+ if (freq <= 0)
+ return -SOS_EINVAL;
+
+ /* Compute counter value */
+ nb_tick = I8254_MAX_FREQ / freq;
+
+ /* Counter must be between 1 and 65536 */
+ if (nb_tick > 65536)
+ return -SOS_EINVAL;
+ if (nb_tick <= 0)
+ return -SOS_EINVAL;
+
+ /* The i8254 interprets 0 to mean counter == 65536, because 65536
+ cannot be coded on 16bits */
+ if (nb_tick == 65536)
+ nb_tick = 0;
+
+ /* We want to configure timer0, we want to send both LSB+MSB to set
+ timer0 freq (-> 0x30), and we configure timer0 in mode 2, ie as a
+ rate generator (-> 0x4) ==> 0x34 */
+ outb(0x34, I8254_CONTROL);
+
+ /* Send LSB of counter first */
+ outb((nb_tick & 0xFF), I8254_TIMER0);
+
+ /* Send MSB of counter */
+ outb((nb_tick >> 8) & 0xFF, I8254_TIMER0);
+
+ return SOS_OK;
+}
diff --git a/sos-code-article2/hwcore/i8254.h b/sos-code-article2/hwcore/i8254.h
new file mode 100644
index 0000000..4838ff4
--- /dev/null
+++ b/sos-code-article2/hwcore/i8254.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_i8259_H_
+#define _SOS_i8259_H_
+
+#include <sos/errno.h>
+
+/**
+ * @file i8254.h PC programmable timer
+ *
+ * Programmable timer routines. See the Intel 82C54 datasheet (on kos
+ * website).
+ *
+ * @see i82C54 datasheet on Kos website.
+ */
+
+/** Change timer interrupt (IRQ 0) frequency */
+sos_ret_t sos_i8254_set_frequency(unsigned int freq);
+
+#endif /* _SOS_i8259_H_ */
diff --git a/sos-code-article2/hwcore/i8259.c b/sos-code-article2/hwcore/i8259.c
new file mode 100644
index 0000000..8391c07
--- /dev/null
+++ b/sos-code-article2/hwcore/i8259.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "ioports.h"
+
+#include "i8259.h"
+
+#define PIC_MASTER 0x20
+#define PIC_SLAVE 0xa0
+
+/** Setup the 8259 PIC */
+sos_ret_t sos_i8259_setup(void)
+{
+ /* Send ICW1: 8086 mode + NOT Single ctrl + call address
+ interval=8 */
+ outb(0x11, PIC_MASTER);
+ outb(0x11, PIC_SLAVE);
+
+ /* Send ICW2: ctrl base address */
+ outb(0x20, PIC_MASTER+1);
+ outb(0x28, PIC_SLAVE+1);
+
+ /* Send ICW3 master: mask where slaves are connected */
+ outb(0x4, PIC_MASTER+1);
+ /* Send ICW3 slave: index where the slave is connected on master */
+ outb(0x2, PIC_SLAVE+1);
+
+ /* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */
+ outb(0x1, PIC_MASTER+1);
+ outb(0x1, PIC_SLAVE+1);
+
+ /* Send OCW1:
+ * Closing all IRQs : waiting for a correct handler The only IRQ
+ * enabled is the cascade (that's why we use 0xFB for the master) */
+ outb(0xFB, PIC_MASTER+1);
+ outb(0xFF, PIC_SLAVE+1);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_i8259_enable_irq_line(int numirq)
+{
+ if(numirq < 8)
+ /* irq on master PIC */
+ outb((inb(PIC_MASTER+1) & ~(1 << numirq)), PIC_MASTER+1);
+ else
+ /* irq on slave PIC */
+ outb((inb(PIC_SLAVE+1) & ~(1 << (numirq-8))), PIC_SLAVE+1);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_i8259_disable_irq_line(int numirq)
+{
+ if(numirq < 8)
+ /* irq on master PIC */
+ outb((inb(PIC_MASTER+1) | (1 << numirq)), PIC_MASTER+1);
+ else
+ /* irq on slave PIC */
+ outb((inb(PIC_SLAVE+1) | (1 << (numirq-8))), PIC_SLAVE+1);
+
+ return SOS_OK;
+}
diff --git a/sos-code-article2/hwcore/i8259.h b/sos-code-article2/hwcore/i8259.h
new file mode 100644
index 0000000..c1771dd
--- /dev/null
+++ b/sos-code-article2/hwcore/i8259.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_i8259_H_
+#define _SOS_i8259_H_
+
+#include <sos/errno.h>
+
+/**
+ * @file i8259.h PIC
+ *
+ * PIC Management routines. See the Intel 8259A datasheet (on kos
+ * website), page 9+. Should be not be used directly: only interrupt.c
+ * should use this.
+ *
+ * @see i8259A datasheet on Kos website.
+ */
+
+/** Setup PIC and Disable all IRQ lines */
+sos_ret_t sos_i8259_setup(void);
+
+sos_ret_t sos_i8259_enable_irq_line(int numirq);
+
+sos_ret_t sos_i8259_disable_irq_line(int numirq);
+
+#endif /* _SOS_i8259_H_ */
diff --git a/sos-code-article2/hwcore/idt.c b/sos-code-article2/hwcore/idt.c
new file mode 100644
index 0000000..51e3a9d
--- /dev/null
+++ b/sos-code-article2/hwcore/idt.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "segment.h"
+
+#include "idt.h"
+
+/**
+ * An entry in the IDT, or "IDTE" in the following, ie a reference to
+ * a interrupt/trap routine or a task gate to handle the sw/hw
+ * interrupts and exceptions.
+ *
+ * @see figure 5-2, intel x86 doc, vol 3
+ */
+struct x86_idt_entry
+{
+ /* Low dword */
+ sos_ui16_t offset_low; /* 15..0, offset of the routine in the segment */
+ sos_ui16_t seg_sel; /* 31..16, the ID of the segment */
+
+ /* High dword */
+ sos_ui8_t reserved:5; /* 4..0 */
+ sos_ui8_t flags:3; /* 7..5 */
+ sos_ui8_t type:3; /* 10..8 (interrupt gate, trap gate...) */
+ sos_ui8_t op_size:1; /* 11 (0=16bits instructions, 1=32bits instr.) */
+ sos_ui8_t zero:1; /* 12 */
+ sos_ui8_t dpl:2; /* 14..13 */
+ sos_ui8_t present:1; /* 15 */
+ sos_ui16_t offset_high; /* 31..16 */
+} __attribute__((packed));
+
+
+/**
+ * The IDT register, which stores the address and size of the
+ * IDT.
+ *
+ * @see Intel x86 doc vol 3, section 2.4, figure 2-4
+ */
+struct x86_idt_register
+{
+ /* The maximum GDT offset allowed to access an entry in the GDT */
+ sos_ui16_t limit;
+
+ /* This is not exactly a "virtual" address, ie an adddress such as
+ those of instructions and data; this is a "linear" address, ie an
+ address in the paged memory. However, in SOS we configure the
+ segmented memory as a "flat" space: the 0-4GB segment-based (ie
+ "virtual") addresses directly map to the 0-4GB paged memory (ie
+ "linear"), so that the "linear" addresses are numerically equal
+ to the "virtual" addresses: this base_addr will thus be the same
+ as the address of the gdt array */
+ sos_ui32_t base_addr;
+} __attribute__((packed, aligned (8)));
+
+
+static struct x86_idt_entry idt[SOS_IDTE_NUM];
+
+sos_ret_t sos_idt_setup()
+{
+ struct x86_idt_register idtr;
+ int i;
+
+ for (i = 0 ;
+ i < SOS_IDTE_NUM ;
+ i++)
+ {
+ struct x86_idt_entry *idte = idt + i;
+
+ /* Setup an empty IDTE interrupt gate, see figure 5-2 in Intel
+ x86 doc, vol 3 */
+ idte->seg_sel = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE);
+ idte->reserved = 0;
+ idte->flags = 0;
+ idte->type = 0x6; /* Interrupt gate (110b) */
+ idte->op_size = 1; /* 32bits instructions */
+ idte->zero = 0;
+
+ /* Disable this IDT entry for the moment */
+ sos_idt_set_handler(i, (sos_vaddr_t)NULL, 0/* Don't care */);
+ }
+
+ /*
+ * Setup the IDT register, see Intel x86 doc vol 3, section 5.8.
+ */
+
+ /* Address of the IDT */
+ idtr.base_addr = (sos_ui32_t) idt;
+
+ /* The limit is the maximum offset in bytes from the base address of
+ the IDT */
+ idtr.limit = sizeof(idt) - 1;
+
+ /* Commit the IDT into the CPU */
+ asm volatile ("lidt %0\n"::"m"(idtr):"memory");
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_idt_set_handler(int index,
+ sos_vaddr_t handler_address,
+ int lowest_priviledge /* 0..3 */)
+{
+ struct x86_idt_entry *idte;
+
+ if ((index < 0) || (index >= SOS_IDTE_NUM))
+ return -SOS_EINVAL;
+ if ((lowest_priviledge < 0) || (lowest_priviledge > 3))
+ return -SOS_EINVAL;
+
+ idte = idt + index;
+ if (handler_address != (sos_vaddr_t)NULL)
+ {
+ idte->offset_low = handler_address & 0xffff;
+ idte->offset_high = (handler_address >> 16) & 0xffff;
+ idte->dpl = lowest_priviledge;
+ idte->present = 1; /* Yes, there is a handler */
+ }
+ else /* Disable this IDT entry */
+ {
+ idte->offset_low = 0;
+ idte->offset_high = 0;
+ idte->dpl = 0;
+ idte->present = 0; /* No, there is no handler */
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_idt_get_handler(int index,
+ sos_vaddr_t *handler_address,
+ int *lowest_priviledge)
+{
+ if ((index < 0) || (index >= SOS_IDTE_NUM))
+ return -SOS_EINVAL;
+
+ if (handler_address != NULL)
+ *handler_address = idt[index].offset_low
+ | (idt[index].offset_high << 16);
+ if (lowest_priviledge != NULL)
+ *lowest_priviledge = idt[index].dpl;
+
+ return SOS_OK;
+}
diff --git a/sos-code-article2/hwcore/idt.h b/sos-code-article2/hwcore/idt.h
new file mode 100644
index 0000000..7afe364
--- /dev/null
+++ b/sos-code-article2/hwcore/idt.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_IDT_H_
+#define _SOS_IDT_H_
+
+/**
+ * @file idt.h
+ *
+ * Manage the x86 Interrupt Descriptor Table, the table which maps the
+ * hardware interrupt lines, hardware exceptions, and software
+ * interrupts, to software routines. We only define "interrupt gate"
+ * IDT entries. Don't use it directly; refer instead to interrupt.c,
+ * exceptions.c and syscall.c.
+ *
+ * @see Intel x86 doc, Vol 3, chapter 5
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+
+/* Mapping of the CPU exceptions in the IDT (imposed by Intel
+ standards) */
+#define SOS_EXCEPT_BASE 0
+#define SOS_EXCEPT_NUM 32
+#define SOS_EXCEPT_MAX (SOS_HWEXCEPT_BASE + SOS_HWEXCEPT_NUM - 1)
+
+/* Mapping of the IRQ lines in the IDT */
+#define SOS_IRQ_BASE 32
+#define SOS_IRQ_NUM 16
+#define SOS_IRQ_MAX (SOS_IRQ_BASE + SOS_IRQ_NUM - 1)
+
+/**
+ * Number of IDT entries.
+ *
+ * @note Must be large enough to map the hw interrupts, the exceptions
+ * (=> total is 48 entries), and the syscall(s). Since our syscall
+ * will be 0x42, it must be >= 0x43. Intel doc limits this to 256
+ * entries, we use this limit.
+ */
+#define SOS_IDTE_NUM 256 /* 0x100 */
+
+/** Initialization routine: all the IDT entries (or "IDTE") are marked
+ "not present". */
+sos_ret_t sos_idt_setup(void);
+
+/**
+ * Enable the IDT entry if handler_address != NULL, with the given
+ * lowest_priviledge.\ Disable the IDT entry when handler_address ==
+ * NULL (the lowest_priviledge parameter is then ignored). Intel doc
+ * says that there must not be more than 256 entries.
+ *
+ * @note IRQ Unsafe
+ */
+sos_ret_t sos_idt_set_handler(int index,
+ sos_vaddr_t handler_address,
+ int lowest_priviledge /* 0..3 */);
+
+
+/**
+ * @note IRQ Unsafe
+ *
+ * @return the handler address and DPL in the 2nd and 3rd
+ * parameters
+ */
+sos_ret_t sos_idt_get_handler(int index,
+ sos_vaddr_t *handler_address,
+ int *lowest_priviledge);
+
+#endif /* _SOS_IDT_H_ */
diff --git a/sos-code-article2/hwcore/ioports.h b/sos-code-article2/hwcore/ioports.h
new file mode 100644
index 0000000..443acb7
--- /dev/null
+++ b/sos-code-article2/hwcore/ioports.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2004 All GPL'ed OS
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_IOPORTS_H_
+#define _SOS_IOPORTS_H_
+
+/**
+ * @ioports.h
+ *
+ * Intel-specific I/O space access routines.
+ */
+
+/* This macro allows to write to an I/O port */
+#define outb(value, port) \
+ __asm__ volatile ( \
+ "outb %b0,%w1" \
+ ::"a" (value),"Nd" (port) \
+ ) \
+
+// read one byte from port
+#define inb(port) \
+({ \
+ unsigned char _v; \
+ __asm__ volatile ( \
+ "inb %w1,%0" \
+ :"=a" (_v) \
+ :"Nd" (port) \
+ ); \
+ _v; \
+})
+
+#endif /* _SOS_IOPORTS_H_ */
diff --git a/sos-code-article2/hwcore/irq.c b/sos-code-article2/hwcore/irq.c
new file mode 100644
index 0000000..6ec3371
--- /dev/null
+++ b/sos-code-article2/hwcore/irq.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "idt.h"
+#include "i8259.h"
+
+#include "irq.h"
+
+/* array of IRQ wrappers, defined in irq_wrappers.S */
+extern sos_vaddr_t sos_irq_wrapper_array[SOS_IRQ_NUM];
+
+/* arrays of IRQ handlers, shared with irq_wrappers.S */
+sos_irq_handler_t sos_irq_handler_array[SOS_IRQ_NUM] = { NULL, };
+
+
+sos_ret_t sos_irq_setup(void)
+{
+ return sos_i8259_setup();
+}
+
+
+sos_ret_t sos_irq_set_routine(int irq_level,
+ sos_irq_handler_t routine)
+{
+ sos_ret_t retval;
+ sos_ui32_t flags;
+
+ if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM))
+ return -SOS_EINVAL;
+
+ sos_disable_IRQs(flags);
+
+ retval = SOS_OK;
+
+ /* Set the irq routine to be called by the IRQ wrapper */
+ sos_irq_handler_array[irq_level] = routine;
+
+ /* If the irq is to be enabled, update the IDT with the IRQ
+ wrapper */
+ if (routine != NULL)
+ {
+ retval
+ = sos_idt_set_handler(SOS_IRQ_BASE + irq_level,
+ (sos_vaddr_t) sos_irq_wrapper_array[irq_level],
+ 0 /* CPL0 routine */);
+ /* A problem occured */
+ if (retval != SOS_OK)
+ sos_irq_handler_array[irq_level] = NULL;
+ }
+ else /* Disable this idt entry */
+ {
+ retval
+ = sos_idt_set_handler(SOS_IRQ_BASE + irq_level,
+ (sos_vaddr_t)NULL /* Disable IDTE */,
+ 0 /* Don't care */);
+ }
+
+ /* Update the PIC only if an IRQ handler has been set */
+ if (sos_irq_handler_array[irq_level] != NULL)
+ sos_i8259_enable_irq_line(irq_level);
+ else
+ sos_i8259_disable_irq_line(irq_level);
+
+ sos_restore_IRQs(flags);
+ return retval;
+}
+
+
+sos_irq_handler_t sos_irq_get_routine(int irq_level)
+{
+ if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM))
+ return NULL;
+
+ /* Expected to be atomic */
+ return sos_irq_handler_array[irq_level];
+}
diff --git a/sos-code-article2/hwcore/irq.h b/sos-code-article2/hwcore/irq.h
new file mode 100644
index 0000000..5b39230
--- /dev/null
+++ b/sos-code-article2/hwcore/irq.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWINTR_H_
+#define _SOS_HWINTR_H_
+
+/**
+ * @file irq.c
+ *
+ * Hardware interrupts routines management.
+ */
+
+#include <sos/errno.h>
+
+#define sos_save_flags(flags) \
+ asm volatile("pushfl ; popl %0":"=g"(flags)::"memory")
+#define sos_restore_flags(flags) \
+ asm volatile("push %0; popfl"::"g"(flags):"memory")
+
+#define sos_disable_IRQs(flags) \
+ ({ sos_save_flags(flags); asm("cli\n"); })
+#define sos_restore_IRQs(flags) \
+ sos_restore_flags(flags)
+
+/* Usual IRQ levels */
+#define SOS_IRQ_TIMER 0
+#define SOS_IRQ_KEYBOARD 1
+#define SOS_IRQ_SLAVE_PIC 2
+#define SOS_IRQ_COM2 3
+#define SOS_IRQ_COM1 4
+#define SOS_IRQ_LPT2 5
+#define SOS_IRQ_FLOPPY 6
+#define SOS_IRQ_LPT1 7
+#define SOS_IRQ_8_NOT_DEFINED 8
+#define SOS_IRQ_RESERVED_1 9
+#define SOS_IRQ_RESERVED_2 10
+#define SOS_IRQ_RESERVED_3 11
+#define SOS_IRQ_RESERVED_4 12
+#define SOS_IRQ_COPROCESSOR 13
+#define SOS_IRQ_HARDDISK 14
+#define SOS_IRQ_RESERVED_5 15
+
+typedef void (*sos_irq_handler_t)(int irq_level);
+
+/** Setup the PIC */
+sos_ret_t sos_irq_setup(void);
+
+/**
+ * If the routine is not NULL, the IDT is setup to call an IRQ
+ * wrapper upon interrupt, which in turn will call the routine, and
+ * the PIC is programmed to raise an irq.\ If the routine is
+ * NULL, we disable the irq line.
+ */
+sos_ret_t sos_irq_set_routine(int irq_level,
+ sos_irq_handler_t routine);
+
+sos_irq_handler_t sos_irq_get_routine(int irq_level);
+
+#endif /* _SOS_HWINTR_H_ */
diff --git a/sos-code-article2/hwcore/irq_wrappers.S b/sos-code-article2/hwcore/irq_wrappers.S
new file mode 100644
index 0000000..cf3355d
--- /dev/null
+++ b/sos-code-article2/hwcore/irq_wrappers.S
@@ -0,0 +1,173 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#define ASM_SOURCE 1
+
+.file "irq_wrappers.S"
+
+.text
+
+/* The address of the table of handlers (defined in irq.c) */
+.extern sos_irq_handler_array
+
+/* The address of the table of wrappers (defined below, and shared
+ with irq.c */
+.globl sos_irq_wrapper_array
+
+
+/* These pre-handlers are for IRQ (Master PIC) */
+.irp id, 0,1,2,3,4,5,6,7
+
+ .p2align 2, 0x90
+
+ sos_irq_wrapper_\id:
+ .type sos_irq_wrapper_\id,@function
+
+ /*
+ * Backup the CPU context
+ */
+
+ /* Fake error code */
+ pushl $0
+
+ /* Backup the actual context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Send EOI to PIC. See Intel 8259 datasheet
+ available on Kos website */
+ movb $0x20, %al
+ outb %al, $0x20
+
+ /*
+ * Call the handler with IRQ number as argument
+ */
+ pushl $\id
+ leal sos_irq_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Remove fake error code */
+ addl $4, %esp
+
+ iret
+ .endr
+
+
+/* These pre-handlers are for IRQ (Slave PIC) */
+.irp id, 8,9,10,11,12,13,14,15
+
+ .p2align 2, 0x90
+
+ sos_irq_wrapper_\id:
+ .type sos_irq_wrapper_\id,@function
+
+ /*
+ * Backup the CPU context
+ */
+
+ /* Fake error code */
+ pushl $0
+
+ /* Backup the actual context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Send EOI to PIC. See Intel 8259 datasheet
+ available on Kos website */
+ movb $0x20, %al
+ outb %al, $0xa0
+ outb %al, $0x20
+
+ /*
+ * Call the handler with IRQ number as argument
+ */
+ pushl $\id
+ leal sos_irq_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Remove fake error code */
+ addl $4, %esp
+
+ iret
+ .endr
+
+/* Build the sos_irq_wrapper_array, shared with irq.c */
+.section ".rodata"
+.p2align 5, 0x0
+sos_irq_wrapper_array:
+ .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .long (sos_irq_wrapper_\id)
+ .endr
diff --git a/sos-code-article2/hwcore/segment.h b/sos-code-article2/hwcore/segment.h
new file mode 100644
index 0000000..37bdf5e
--- /dev/null
+++ b/sos-code-article2/hwcore/segment.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWSEGS_H_
+#define _SOS_HWSEGS_H_
+
+/**
+ * @file segments.h
+ *
+ * Global and local (GDT/LDT) segment descriptor definition and
+ * structure. These segments map virtual addresses (ie
+ * data/instruction addresses, relative to these segment descriptors)
+ * to linear addresses (ie addresses in the paged-memory space).
+ *
+ * @see Intel x86 doc, vol 3 chapter 3.
+ */
+
+#include <sos/types.h>
+
+/*
+ * Global segment selectors (GDT) for SOS/x86.
+ *
+ * @see gdt.h
+ */
+#define SOS_SEG_NULL 0 /* NULL segment, unused by the procesor */
+#define SOS_SEG_KCODE 1 /* Kernel code segment */
+#define SOS_SEG_KDATA 2 /* Kernel data segment */
+
+
+/**
+ * Helper macro that builds a segment register's value
+ */
+#define SOS_BUILD_SEGMENT_REG_VALUE(desc_privilege,in_ldt,seg_index) \
+ ( (((desc_privilege) & 0x3) << 0) \
+ | (((in_ldt)?1:0) << 2) \
+ | ((seg_index) << 3) )
+
+
+/*
+ * Local segment selectors (LDT) for SOS/x86
+ */
+/* None */
+
+#endif /* _SOS_HWSEGS_H_ */
diff --git a/sos-code-article2/sos.elf b/sos-code-article2/sos.elf
new file mode 100755
index 0000000..0898db5
--- /dev/null
+++ b/sos-code-article2/sos.elf
Binary files differ
diff --git a/sos-code-article2/sos.map b/sos-code-article2/sos.map
new file mode 100644
index 0000000..ea0519f
--- /dev/null
+++ b/sos-code-article2/sos.map
@@ -0,0 +1,106 @@
+00201000 __b_kernel
+00200000 __b_load
+00202d6b clk_it
+00203940 clock_count.1103
+00202ce0 display_bits
+00203944 div_count.1107
+00202da3 divide_ex
+00207950 __e_kernel
+00203066 __e_load
+00202f00 gdt
+00203080 idt
+00201011 loop
+0020278b memcmp
+00202734 memcpy
+00202765 memset
+00201000 multiboot_entry
+00200000 multiboot_header
+00202cab snprintf
+00202629 sos_bochs_hexdump
+002026ee sos_bochs_printf
+0020244b sos_bochs_puthex
+00202426 sos_bochs_putstring
+0020241c sos_bochs_setup
+002012d0 sos_exception_get_routine
+00203880 sos_exception_handler_array
+0020123d sos_exception_set_routine
+00201218 sos_exceptions_setup
+00201300 sos_exception_wrapper_0
+00201344 sos_exception_wrapper_1
+002019a4 sos_exception_wrapper_10
+002019e4 sos_exception_wrapper_11
+00201a24 sos_exception_wrapper_12
+00201a64 sos_exception_wrapper_13
+00201aa4 sos_exception_wrapper_14
+00201564 sos_exception_wrapper_15
+002015a8 sos_exception_wrapper_16
+00201ae4 sos_exception_wrapper_17
+002015ec sos_exception_wrapper_18
+00201630 sos_exception_wrapper_19
+00201388 sos_exception_wrapper_2
+00201674 sos_exception_wrapper_20
+002016b8 sos_exception_wrapper_21
+002016fc sos_exception_wrapper_22
+00201740 sos_exception_wrapper_23
+00201784 sos_exception_wrapper_24
+002017c8 sos_exception_wrapper_25
+0020180c sos_exception_wrapper_26
+00201850 sos_exception_wrapper_27
+00201894 sos_exception_wrapper_28
+002018d8 sos_exception_wrapper_29
+002013cc sos_exception_wrapper_3
+0020191c sos_exception_wrapper_30
+00201960 sos_exception_wrapper_31
+00201410 sos_exception_wrapper_4
+00201454 sos_exception_wrapper_5
+00201498 sos_exception_wrapper_6
+002014dc sos_exception_wrapper_7
+00201b24 sos_exception_wrapper_8
+00201520 sos_exception_wrapper_9
+00202f20 sos_exception_wrapper_array
+002011e4 sos_gdt_setup
+002021a8 sos_i8254_set_frequency
+0020214e sos_i8259_disable_irq_line
+002020f0 sos_i8259_enable_irq_line
+002020a0 sos_i8259_setup
+00201174 sos_idt_get_handler
+002010b9 sos_idt_set_handler
+00201014 sos_idt_setup
+00201bfe sos_irq_get_routine
+00203900 sos_irq_handler_array
+00201b35 sos_irq_set_routine
+00201b28 sos_irq_setup
+00201c20 sos_irq_wrapper_0
+00201c68 sos_irq_wrapper_1
+00201ef0 sos_irq_wrapper_10
+00201f38 sos_irq_wrapper_11
+00201f80 sos_irq_wrapper_12
+00201fc8 sos_irq_wrapper_13
+00202010 sos_irq_wrapper_14
+00202058 sos_irq_wrapper_15
+00201cb0 sos_irq_wrapper_2
+00201cf8 sos_irq_wrapper_3
+00201d40 sos_irq_wrapper_4
+00201d88 sos_irq_wrapper_5
+00201dd0 sos_irq_wrapper_6
+00201e18 sos_irq_wrapper_7
+00201e60 sos_irq_wrapper_8
+00201ea8 sos_irq_wrapper_9
+00202fa0 sos_irq_wrapper_array
+00202ddb sos_main
+00202240 sos_x86_videomem_cls
+0020238a sos_x86_videomem_printf
+00202313 sos_x86_videomem_putchar
+00202283 sos_x86_videomem_putstring
+00202220 sos_x86_videomem_setup
+00203950 stack
+00201000 start
+00201000 _start
+002028d9 strcmp
+002027e5 strlen
+0020291b strncmp
+0020280a strnlen
+0020288e strzcat
+0020283d strzcpy
+00202f18 video
+0020297c vsnprintf
diff --git a/sos-code-article2/sos/assert.h b/sos-code-article2/sos/assert.h
new file mode 100644
index 0000000..a14ca0b
--- /dev/null
+++ b/sos-code-article2/sos/assert.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2004 The KOS Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ASSERT_H_
+#define _SOS_ASSERT_H_
+
+#include <drivers/bochs.h>
+#include <drivers/x86_videomem.h>
+
+/**
+ * If the expr is FALSE, print a message and halt the machine
+ */
+#define SOS_ASSERT_FATAL(expr) \
+ ({ \
+ int __res=(int)(expr); \
+ if (! __res) { \
+ asm("cli\n"); /* disable interrupts -- x86 only */ \
+ sos_bochs_printf("%s@%s:%d Assertion " # expr " failed\n", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ sos_x86_videomem_printf(24, 0, 12, \
+ "%s@%s:%d Assertion " # expr " failed", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ for (;;) asm("hlt;") ; /* Infinite loop, ie simple system halt */ \
+ } \
+ })
+
+
+#endif /* _SOS_ASSERT_H_ */
diff --git a/sos-code-article2/sos/errno.h b/sos-code-article2/sos/errno.h
new file mode 100644
index 0000000..f13e740
--- /dev/null
+++ b/sos-code-article2/sos/errno.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ERRNO_H_
+#define _SOS_ERRNO_H_
+
+/**
+ * @file errno.h
+ *
+ * SOS return value codes and errors.
+ */
+
+/* Positive values of the error codes */
+#define SOS_OK 0 /* No error */
+#define SOS_EINVAL 1 /* Invalid argument */
+#define SOS_ENOSUP 2 /* Operation not supported */
+#define SOS_EFATAL 255 /* Internal fatal error */
+
+/* A negative value means that an error occured. For
+ * example -SOS_EINVAL means that the error was "invalid
+ * argument" */
+typedef int sos_ret_t;
+
+#endif /* _SOS_ERRNO_H_ */
diff --git a/sos-code-article2/sos/klibc.c b/sos-code-article2/sos/klibc.c
new file mode 100644
index 0000000..277a15c
--- /dev/null
+++ b/sos-code-article2/sos/klibc.c
@@ -0,0 +1,271 @@
+/* Copyright (C) 2004 David Decotigny (with INSA Rennes for vsnprintf)
+ Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "klibc.h"
+
+/* For an optimized version, see BSD sources ;) */
+void *memcpy(void *dst0, const void *src0, register unsigned int size)
+{
+ char *dst;
+ const char *src;
+ for (dst = (char*)dst0, src = (const char*)src0 ;
+ size > 0 ;
+ dst++, src++, size--)
+ *dst = *src;
+ return dst0;
+}
+
+/* ditto */
+void *memset(void *dst0, register int c, register unsigned int length)
+{
+ char *dst;
+ for (dst = (char*) dst0 ;
+ length > 0 ;
+ dst++, length --)
+ *dst = (char)c;
+ return dst0;
+}
+
+int memcmp(const void *s1, const void *s2, sos_size_t len)
+{
+ const unsigned char *c1, *c2;
+ unsigned int i;
+
+ for (i = 0, c1 = s1, c2 = s2; i < len; i++, c1++, c2++)
+ {
+ if(*c1 != *c2)
+ return *c1 - *c2;
+ }
+
+ return 0;
+}
+
+
+unsigned int strlen(register const char *str)
+{
+ unsigned int retval = 0;
+
+ while (*str++)
+ retval++;
+
+ return retval;
+}
+
+
+unsigned int strnlen(const char * s, sos_size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */continue;
+
+ return sc - s;
+}
+
+
+char *strzcpy(register char *dst, register const char *src, register int len)
+{
+ int i;
+
+ if (len <= 0)
+ return dst;
+
+ for (i = 0; i < len; i++)
+ {
+ dst[i] = src[i];
+ if(src[i] == '\0')
+ return dst;
+ }
+
+ dst[len-1] = '\0';
+ return dst;
+}
+
+
+char *strzcat (char *dest, const char *src, sos_size_t n)
+{
+ char *res = dest;
+
+ for ( ; *dest ; dest++);
+
+ for ( ; *src ; src++, dest++) {
+ *dest = *src;
+ n--;
+ if (n <= 0)
+ break;
+ }
+
+ *dest = '\0';
+ return res;
+}
+
+int strcmp(register const char *s1, register const char *s2)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == 0)
+ return (0);
+
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
+
+
+int strncmp(register const char *s1, register const char *s2, register int len)
+{
+ char c1 = '\0', c2 = '\0';
+
+ while (len > 0)
+ {
+ c1 = (unsigned char) *s1++;
+ c2 = (unsigned char) *s2++;
+ if (c1 == '\0' || c1 != c2)
+ return c1 - c2;
+ len--;
+ }
+
+ return c1 - c2;
+}
+
+
+/* I (d2) borrowed and rewrote this for Nachos/INSA Rennes. Thanks to
+ them for having kindly allowed me to do so. */
+int vsnprintf(char *buff, sos_size_t len, const char * format, va_list ap)
+{
+ sos_size_t i, result;
+
+ if (!buff || !format || (len < 0))
+ return -1;
+
+#define PUTCHAR(thechar) \
+ do { \
+ if (result < len-1) \
+ *buff++ = (thechar); \
+ result++; \
+ } while (0)
+
+ result = 0;
+ for(i=0 ; format[i] != '\0' ; i++){
+ switch (format[i])
+ {
+ case '%':
+ i++;
+ switch(format[i])
+ {
+ case '%':
+ {
+ PUTCHAR('%');
+ break;
+ }
+ case 'i':;
+ case 'd':
+ {
+ int integer = va_arg(ap,int);
+ int cpt2 = 0;
+ char buff_int[16];
+
+ if (integer<0)
+ PUTCHAR('-');
+ /* Ne fait pas integer = -integer ici parce que INT_MIN
+ n'a pas d'equivalent positif (int = [-2^31, 2^31-1]) */
+
+ do {
+ int m10 = integer%10;
+ m10 = (m10 < 0)? -m10:m10;
+ buff_int[cpt2++]=(char)('0'+ m10);
+ integer=integer/10;
+ } while(integer!=0);
+
+ for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
+ PUTCHAR(buff_int[cpt2]);
+
+ break;
+ }
+
+ case 'c':
+ {
+ int value = va_arg(ap,int);
+ PUTCHAR((char)value);
+ break;
+ }
+
+ case 's':
+ {
+ char *string = va_arg(ap,char *);
+ if (! string)
+ string = "(null)";
+ for( ; *string != '\0' ; string++)
+ PUTCHAR(*string);
+ break;
+ }
+
+ case 'x':
+ {
+ unsigned int hexa = va_arg(ap,int);
+ unsigned int nb;
+ int i, had_nonzero = 0;
+ for(i=0 ; i < 8 ; i++)
+ {
+ nb = (unsigned int)(hexa << (i*4));
+ nb = (nb >> 28) & 0xf;
+ // Skip the leading zeros
+ if (nb == 0)
+ {
+ if (had_nonzero)
+ PUTCHAR('0');
+ }
+ else
+ {
+ had_nonzero = 1;
+ if (nb < 10)
+ PUTCHAR('0'+nb);
+ else
+ PUTCHAR('a'+(nb-10));
+ }
+ }
+ if (! had_nonzero)
+ PUTCHAR('0');
+ break;
+ }
+ break;
+
+ default:
+ PUTCHAR('%');
+ PUTCHAR(format[i]);
+ }
+ break;
+
+ default:
+ PUTCHAR(format[i]);
+ }
+ }
+
+ *buff = '\0';
+ return result;
+}
+
+
+int snprintf(char * buff, sos_size_t len, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ len = vsnprintf(buff, len, format, ap);
+ va_end(ap);
+
+ return len;
+}
diff --git a/sos-code-article2/sos/klibc.h b/sos-code-article2/sos/klibc.h
new file mode 100644
index 0000000..a8b9d49
--- /dev/null
+++ b/sos-code-article2/sos/klibc.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_KLIBC_H_
+#define _SOS_KLIBC_H_
+
+/**
+ * @file klibc.h
+ *
+ * Basic libc-style support for common useful functions (string.h,
+ * stdarg.h), some with slight non-standard behavior (see comments).
+ */
+
+#include <sos/types.h>
+
+/* string.h functions */
+
+void *memcpy(void *dst, const void *src, register unsigned int size ) ;
+void *memset(void *dst, register int c, register unsigned int length ) ;
+int memcmp(const void *s1, const void *s2, sos_size_t n);
+
+unsigned int strlen( register const char *str) ;
+unsigned int strnlen(const char * s, sos_size_t maxlen);
+
+/**
+ * @note Same as strncpy(), with a slightly different semantic.
+ * Actually, strncpy(3C) says " The result will not be null-terminated
+ * if the length of 'from' is n or more.". Here, 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcpy( register char *dst, register const char *src,
+ register int len ) ;
+
+/**
+ * @note Same as strncat(), with the same semantic : 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcat (char *dest, const char *src,
+ const sos_size_t len);
+
+int strcmp(register const char *s1, register const char *s2 );
+int strncmp(register const char *s1, register const char *s2,
+ register int len );
+
+/* Basic stdarg.h macros. Taken from gcc support files */
+#define __GNUC_VA_LIST
+typedef void *__gnuc_va_list;
+typedef __gnuc_va_list va_list;
+#define __va_rounded_size(TYPE) \
+ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+#define va_start(AP, LASTARG) \
+ (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG)))
+#define va_end(AP) \
+ ((void)0)
+#define va_arg(AP, TYPE) \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
+ *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
+#define __va_copy(dest, src) \
+ (dest) = (src)
+
+/* stdarg.h functions. There might be a non-standard behavior: there
+ will always be a trailing '\0' in the resulting string */
+int vsnprintf(char *, sos_size_t, const char *, va_list);
+int snprintf(char *, sos_size_t, const char *, /*args*/ ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+#endif /* _SOS_KLIBC_H_ */
diff --git a/sos-code-article2/sos/main.c b/sos-code-article2/sos/main.c
new file mode 100644
index 0000000..9d897b0
--- /dev/null
+++ b/sos-code-article2/sos/main.c
@@ -0,0 +1,152 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* Include definitions of the multiboot standard */
+#include <bootstrap/multiboot.h>
+#include <hwcore/idt.h>
+#include <hwcore/gdt.h>
+#include <hwcore/irq.h>
+#include <hwcore/exception.h>
+#include <hwcore/i8254.h>
+#include <sos/klibc.h>
+#include <sos/assert.h>
+#include <drivers/x86_videomem.h>
+#include <drivers/bochs.h>
+
+
+/* Helper function to display each bits of a 32bits integer on the
+ screen as dark or light carrets */
+static void display_bits(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ sos_ui32_t integer)
+{
+ int i;
+ /* Scan each bit of the integer, MSb first */
+ for (i = 31 ; i >= 0 ; i--)
+ {
+ /* Test if bit i of 'integer' is set */
+ int bit_i = (integer & (1 << i));
+ /* Ascii 219 => dark carret, Ascii 177 => light carret */
+ unsigned char ascii_code = bit_i?219:177;
+ sos_x86_videomem_putchar(row, col++,
+ attribute,
+ ascii_code);
+ }
+}
+
+
+/* Clock IRQ handler */
+static void clk_it(int intid)
+{
+ static sos_ui32_t clock_count = 0;
+
+ display_bits(0, 48,
+ SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
+ clock_count);
+ clock_count++;
+
+}
+
+/* Division by zero exception handler */
+static void divide_ex(int exid)
+{
+ static sos_ui32_t div_count = 0;
+ display_bits(0, 0,
+ SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,
+ div_count);
+ div_count++;
+}
+
+/* The C entry point of our operating system */
+void sos_main(unsigned long magic, unsigned long addr)
+{
+ unsigned i;
+
+ /* Grub sends us a structure, called multiboot_info_t with a lot of
+ precious informations about the system, see the multiboot
+ documentation for more information. */
+ multiboot_info_t *mbi;
+ mbi = (multiboot_info_t *) addr;
+
+ /* Setup bochs and console, and clear the console */
+ sos_bochs_setup();
+
+ sos_x86_videomem_setup();
+ sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
+
+ /* Greetings from SOS */
+ if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
+ /* Loaded with Grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
+ "SOS", ',',
+ (unsigned)(mbi->mem_upper >> 10) + 1,
+ (unsigned)mbi->mem_upper);
+ else
+ /* Not loaded with grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome to SOS");
+
+ sos_bochs_putstring("Message in a bochs\n");
+
+ /* Setup CPU segmentation and IRQ subsystem */
+ sos_gdt_setup();
+ sos_idt_setup();
+
+ /* Setup SOS IRQs and exceptions subsystem */
+ sos_exceptions_setup();
+ sos_irq_setup();
+
+ /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */
+ sos_i8254_set_frequency(100);
+
+
+ /* Binding some HW interrupts and exceptions to software routines */
+ sos_irq_set_routine(SOS_IRQ_TIMER,
+ clk_it);
+ sos_exception_set_routine(SOS_EXCEPT_DIVIDE_ERROR,
+ divide_ex);
+ /* Enabling the HW interrupts here, this will make the timer HW
+ interrupt call our clk_it handler */
+ asm volatile ("sti\n");
+
+ /* Raise a rafale of 'division by 0' exceptions. All this code is
+ not really needed (equivalent to a bare "i=1/0;"), except when
+ compiling with -O3: "i=1/0;" is considered dead code with gcc
+ -O3. */
+ i = 10;
+ while (1)
+ {
+ /* Stupid function call to fool gcc optimizations */
+ sos_bochs_printf("i = 1 / %d...\n", i);
+ i = 1 / i;
+ }
+
+ /* Will never print this since the "divide by zero" exception always
+ returns to the faulting instruction (see Intel x86 doc vol 3,
+ section 5.12), thus re-evaluating the "divide-by-zero" exprssion
+ and raising the "divide by zero" exception again and again... */
+ sos_x86_videomem_putstring(2, 0,
+ SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,
+ "Invisible");
+
+ return;
+}
diff --git a/sos-code-article2/sos/types.h b/sos-code-article2/sos/types.h
new file mode 100644
index 0000000..b6efae9
--- /dev/null
+++ b/sos-code-article2/sos/types.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_TYPES_H_
+#define _SOS_TYPES_H_
+
+/**
+ * @file types.h
+ *
+ * SOS basic types definition
+ */
+
+/** Generic virtual address (kernel or user) */
+typedef unsigned int sos_vaddr_t;
+
+/** Memory size of an object (positive) */
+typedef unsigned int sos_size_t;
+
+/** Low-level sizes */
+typedef unsigned long int sos_ui32_t; /* 32b unsigned */
+typedef unsigned short int sos_ui16_t; /* 16b unsigned */
+typedef unsigned char sos_ui8_t; /* 8b unsigned */
+
+typedef enum { FALSE=0, TRUE } sos_bool_t;
+
+/** Not a proper type, but highly useful with basic type
+ manipulations */
+#define NULL ((void*)0)
+
+#endif /* _SOS_TYPES_H_ */
diff --git a/sos-code-article2/support/build_image.sh b/sos-code-article2/support/build_image.sh
new file mode 100755
index 0000000..43929cd
--- /dev/null
+++ b/sos-code-article2/support/build_image.sh
@@ -0,0 +1,215 @@
+#!/bin/sh
+# Copyright (C) 2003, David Decotigny
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# 1) What does it do ?
+#
+# 1) Check where Grub is installed (lookup_grub)
+# 2) Assign some local variables using the shell script arguments.
+# a) Argument 1 : the destination (either a file or a drive, like a:)
+# b) Argument 2 : the loader (i.e kernel)
+# c) Argument 3 : options passed to the loader
+# d) Argument 4 : the modules (that can be loaded optionally by Grub)
+# 3) Test whether destination is a drive or a file
+# 4) Create the directory structure inside the drive
+# 5) Copy the loader in the drive
+# 6) Generate the 'menu.txt' file used by Grub to generate the boot menu
+# 7) Copy all modules
+# 8) Copy the menu.txt file
+#
+# 2) Why is it so complex ?
+# Because it must support various Grub/mtools installations and versions
+#
+# In fact, this shell script is used in the KOS (kos.enix.org)
+# project. This operating system consists in a loader and many many
+# modules that are linked together at boot time. It is much more
+# complex that a simple monolithic kernel.
+#
+# For your simple monolithic kernel, you only need to give argument 1
+# and 2.
+
+print_usage () {
+ echo "Usage: $0 [X:|image] path/to/loader option path/to/modules..."
+ echo " where X: is a valid floppy drive on your computer"
+ echo " where image is any file name"
+ exit 1
+}
+
+grub_dirs_common="/usr/local/share/grub/i386-freebsd /usr/local/share/grub/i386-pc /usr/share/grub/i386-pc /usr/lib/grub/i386-pc /usr/local/grub /usr/share/grub/i386-redhat /usr/local/src/grub-0.5.94 $HOME/share/grub/i386-pc/"
+sbin_grub_path="/usr/local/sbin /usr/sbin /sbin $HOME/sbin"
+
+PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
+export PATH
+
+MTOOLSRC=mtoolsrc
+export MTOOLSRC
+
+# Redefined variables
+FLOPPY_DRIVE=A:
+IMG_FNAME=fd.img
+
+##
+## Format disk image
+##
+init_image () {
+ echo "Initialize disk image $IMG_FILE..."
+ if [ ! -f $IMG_FNAME ] ; then
+ dd if=/dev/zero of=$IMG_FNAME bs=18k count=80 1>/dev/null 2>&1
+ fi
+
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M filter" > $MTOOLSRC
+
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M" > $MTOOLSRC
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\"" > $MTOOLSRC
+ mformat U:
+ fi
+ fi
+}
+
+
+##
+## Format (real) floppy disk
+##
+init_floppy () {
+ echo "Formatting floppy..."
+ mformat $FLOPPY_DRIVE || exit 1
+}
+
+
+lookup_grub () {
+ # Look for a correct GRUBDIR
+ for d in $grub_dirs_common ; do
+ if [ -d $d ] ; then
+ GRUBDIR=$d
+ break
+ fi
+ done
+
+ # Try to guess with locate
+ if [ ! -d "$GRUBDIR" ] ; then
+ GRUBDIR=`locate stage2 | head -1 | xargs dirname 2>/dev/null`
+ fi
+
+ # Look for a correct sbin/grub
+ for d in $sbin_grub_path ; do
+ if [ -x $d/grub ] ; then
+ SBIN_GRUB=$d/grub
+ break
+ fi
+ done
+
+ if [ -d "$GRUBDIR" -a -x "$SBIN_GRUB" ] ; then
+ echo "Found correct grub installation in $GRUBDIR"
+ echo "Found correct /sbin/grub at $SBIN_GRUB"
+ else
+ echo "Couldn't find a correct grub installation."
+ exit 1
+ fi
+}
+
+##
+## setup_disk [drive]
+## => setup disk directory structure / copy files
+##
+setup_disk () {
+ echo "Setup destination disk..."
+
+ mmd $1/boot
+ mmd $1/boot/grub
+
+ if [ -d $GRUBDIR/stage1 ] ; then
+ mcopy $GRUBDIR/stage1/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2/stage2 $1/boot/grub/
+ else
+ mcopy $GRUBDIR/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2 $1/boot/grub/
+ fi
+ mmd $1/system
+ mmd $1/modules
+
+ $SBIN_GRUB --batch <<EOT 1>/dev/null 2>/dev/null || exit 1
+device (fd0) $IMG_FNAME
+install (fd0)/boot/grub/stage1 (fd0) (fd0)/boot/grub/stage2 p (fd0)/boot/grub/menu.txt
+quit
+EOT
+}
+
+
+
+#################################################
+## Real start
+##
+#[ "$#" -lt 3 ] && print_usage
+
+lookup_grub
+
+dest="$1" ; shift
+loader_fname="$1" ; shift
+options="$1" ; shift
+modules="$*"
+
+# Init destination disk
+case x$dest in
+ x*:)
+ drive=$dest
+ IMG_FNAME=$dest
+ FLOPPY_DRIVE=$dest
+ init_floppy
+ ;;
+ x*)
+ drive=U:
+ IMG_FNAME=$dest
+ init_image
+ ;;
+esac
+
+# Create directory structure
+setup_disk $drive
+
+# Copy the loader
+mcopy -bo $loader_fname $drive/system/`basename $loader_fname`
+
+# Generate the menu.txt file
+rm -f menu.txt
+cat <<EOF > menu.txt
+timeout 0
+default 0
+title Simple OS
+root (fd0)
+kernel /system/`basename $loader_fname` $options
+EOF
+
+# Copy the modules
+for f in $modules ; do
+ if [ ! -f $f ] ; then
+ echo "ERROR: module $f not correctly compiled in."
+ exit 1
+ fi
+ if ! mcopy -bo $f $drive/modules/`basename $f` ; then
+ echo "ERROR: module $f could not be transferred to floppy."
+ exit 1
+ fi
+ echo module /modules/`basename $f` >> menu.txt
+done
+
+# Transfers the menu.txt file to floppy
+mcopy -bo menu.txt $drive/boot/grub/
diff --git a/sos-code-article2/support/sos.lds b/sos-code-article2/support/sos.lds
new file mode 100644
index 0000000..4d87061
--- /dev/null
+++ b/sos-code-article2/support/sos.lds
@@ -0,0 +1,107 @@
+/* Copyright (C) 2003, Thomas Petazzoni
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* We generate binary in the ELF format */
+OUTPUT_FORMAT("elf32-i386","elf32-i386","elf32-i386");
+
+/* The entry point is _start (defined in boot.S) */
+ENTRY(_start)
+
+/* The architecture is i386 */
+OUTPUT_ARCH("i386")
+
+SECTIONS
+{
+ /* our kernel is loaded at 0x200000 */
+ . = 0x200000;
+ __b_load = .;
+
+ /* the multiboot header MUST come early enough in the output
+ object file */
+ .multiboot :
+ {
+ /* The multiboot section (containing the multiboot header)
+ goes here */
+ *(.multiboot);
+
+ /*
+ * With the following line, we force this section to be
+ * allocated in the output file as soon as possible, no matter
+ * when the file containing the multiboot header (multiboot.S)
+ * is compiled. This is to conform to the multiboot spec, which
+ * says "The Multiboot header must be contained completely
+ * within the first 8192 bytes of the OS image, and must be
+ * longword (32-bit) aligned."
+ */
+ LONG(0);
+ }
+
+ /* Defines a symbol '__b_kernel to mark the start of the kernel
+ code/data */
+ . = ALIGN(4096);
+ __b_kernel = .;
+
+ /* Beginning of the text section */
+ .text ALIGN(4096) :
+ {
+ /* This section includes the code */
+ *(.text*)
+ /* Defines the 'etext' and '_etext' at the end */
+ PROVIDE(etext = .);
+ PROVIDE(_etext = .);
+ }
+
+ /* Beginning of the data section */
+ .data . :
+ { *(.data*)
+ PROVIDE(edata = .);
+ PROVIDE(_edata = .);
+ }
+
+ /* Beginning of the read-only data section */
+ .rodata . :
+ { *(.rodata*)
+ PROVIDE(erodata = .);
+ PROVIDE(_erodata = .);
+ }
+ /* We take note of the end of the data to load */
+ __e_load = .;
+
+ /* Beginning of the BSS section (global uninitialized data) */
+ .bss SIZEOF(.rodata) + ADDR(.rodata) :
+ { *(.bss)
+ *(COMMON)
+ PROVIDE(ebss = .);
+ PROVIDE(_ebss = .);
+ }
+
+ /* We take note of the end of the kernel */
+ __e_kernel = .;
+
+ /* We don't care of the note, indent, comment, etc.. sections
+ generated by gcc */
+ /DISCARD/ :{
+ *(.note*)
+ *(.indent)
+ *(.comment)
+ *(.stab)
+ *(.stabstr)
+ }
+
+}
+
diff --git a/sos-code-article3/INSTALL b/sos-code-article3/INSTALL
new file mode 100644
index 0000000..7c7d619
--- /dev/null
+++ b/sos-code-article3/INSTALL
@@ -0,0 +1,118 @@
+
+ SOS: A Simple Operating System
+
+ Compilation/Installation/Test instructions
+
+
+Compilation
+===========
+
+IMPORTANT
+---------
+
+Don't forget to run 'make clean' before 'make' after you have modified
+any source or header file(s).
+
+
+On a x86 host where grub is correctly installed
+-----------------------------------------------
+
+Simply run 'make'
+
+
+On a non-x86 host (without grub of course !)
+--------------------------------------------
+
+See extra/README
+
+
+On an x86 host without Grub, or with a buggy Grub
+-------------------------------------------------
+
+See extra/README
+
+How do I know I have a buggy grub installation ? Answer: in the qemu
+PC emulator, Grub hangs while loading the kernel
+
+
+Installation
+============
+
+Nothing special to do besides compiling
+
+
+Test the SOS Kernel
+===================
+
+On a x86 real machine with Grub installed
+-----------------------------------------
+
+ 1st method
+ => Boot the sos.elf file (append 'kernel=<path_to>sos.elf' in the
+ menu.lst or type it on Grub's command line) from a hard disk, a
+ floppy, or from the network
+
+ 2nd method
+ => Copy the file 'fd.img' to a floppy and boot from it
+
+
+On a x86 real machine without Grub installed
+--------------------------------------------
+
+ 1st method
+ => see extra/README to compile with the grub floppy image we provide,
+ copy the file 'fd.img' to a floppy, and boot from it
+
+ 2nd method
+ => see extra/README to compile with the boot sector we provide (up to
+ article 2 only), copy the file 'extra/sos_bsect.img' to a floppy,
+ and boot from it
+
+
+Inside a PC emulator (x86 and non-x86 hosts)
+--------------------------------------------
+
+Tested on both the bochs emulator (x86/linux, sparc/solaris and
+ppc/linux hosts, 'apt-get install bochs-x vgabios' on debian
+testing/unstable), and the qemu system emulator (with libsdl
+installed: 'apt-get install libsdl1.2-dev' on debian
+testing/unstable).
+
+ 1/ Grub is installed on the host (x86 hosts only)
+ - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ bochs: boot from the file 'fd.img'. Example of a ~/.bochsrc:
+ floppya: 1_44=/home/d2/sos/fd.img, status=inserted
+ romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
+ vgaromimage: /usr/share/vgabios/vgabios.bin
+ megs:63 # 63 Mo de RAM
+
+ qemu: run 'qemu -fda fd.img'
+ If grub hangs while loading the kernel, please go to method 2/
+
+ 2/ Grub is not installed (all hosts)
+ - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the Grub floppy
+ image we provide, and:
+
+ bochs: boot from the file 'fd.img'
+
+ qemu: run 'qemu -fda fd.img'
+
+ 3/ Bonus: boot with the bootsector we provide (all hosts, up to art. 2 ONLY !)
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the boot sector we
+ provide, and:
+
+ bochs: boot from the file 'extra/sos_bsect.img'
+
+ qemu: run 'qemu -fda extra/sos_qemu.img'
+
+ NOTE: After article 2, this way of booting is not supported: please
+ use the method 2/ above.
+
+
+--
+David Decotigny
diff --git a/sos-code-article3/LICENSE b/sos-code-article3/LICENSE
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/sos-code-article3/LICENSE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/sos-code-article3/Makefile b/sos-code-article3/Makefile
new file mode 100644
index 0000000..8e15812
--- /dev/null
+++ b/sos-code-article3/Makefile
@@ -0,0 +1,44 @@
+CC=gcc
+CFLAGS = -Wall -nostdlib -nostdinc -ffreestanding -DKERNEL_SOS
+LDFLAGS = --warn-common
+OBJECTS = bootstrap/multiboot.o \
+ hwcore/idt.o hwcore/gdt.o \
+ hwcore/exception.o hwcore/exception_wrappers.o \
+ hwcore/irq.o hwcore/irq_wrappers.o hwcore/i8259.o \
+ hwcore/i8254.o drivers/x86_videomem.o drivers/bochs.o \
+ sos/physmem.o sos/klibc.o sos/main.o
+
+KERNEL_OBJ = sos.elf
+MULTIBOOT_IMAGE = fd.img
+PWD := $(shell pwd)
+
+# Main target
+all: $(MULTIBOOT_IMAGE)
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ)
+ ./support/build_image.sh $@ $<
+
+$(KERNEL_OBJ): $(OBJECTS) ./support/sos.lds
+ $(LD) $(LDFLAGS) -T ./support/sos.lds -o $@ $(OBJECTS)
+ -nm -C $@ | cut -d ' ' -f 1,3 > sos.map
+
+-include .mkvars
+
+# Create objects from C source code
+%.o: %.c
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -o $@
+
+# Create objects from assembler (.S) source code
+%.o: %.S
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -DASM_SOURCE=1 -o $@
+
+# Clean directory
+clean:
+ $(RM) *.img *.o mtoolsrc *~ menu.txt *.img *.elf *.bin *.map
+ $(RM) *.log *.out bochs*
+ $(RM) bootstrap/*.o bootstrap/*~
+ $(RM) drivers/*.o drivers/*~
+ $(RM) hwcore/*.o hwcore/*~
+ $(RM) sos/*.o sos/*~
+ $(RM) support/*~
+ $(RM) extra/*~
diff --git a/sos-code-article3/README b/sos-code-article3/README
new file mode 100644
index 0000000..efbbc89
--- /dev/null
+++ b/sos-code-article3/README
@@ -0,0 +1,90 @@
+
+ SOS: A Simple Operating System
+
+
+This is SOS, a Simple Operating System for i386-family
+processors. This is as simple as possible to show a way to program a
+basic Operating System on real common hardware (PC). The code should
+be easily readable and understandable thanks to frequent comments, and
+references to external documentation. We chose to implement the basic
+features of an OS, thus making design decisions targetting towards
+simplicity of understanding, covering most of the OS classical
+concepts, but not aiming at proposing yet another full-fledged
+competitive OS (Linux is quite good at it). However, for those who
+would like to propose some enhancements, we are open to any code
+suggestions (patches only, please). And yes, there might be bugs in
+the code, so please send us any bug report, and/or patches !
+
+The OS comes as a set of articles (in french) to be published in the
+journal "Linux Magazine France". Each month, the part of the code
+related to the current article's theme is released (see VERSION file),
+and the resulting OS can be successfully compiled and run, by booting
+it from a floppy on a real machine (tested AMD k7, Cyrix and Intel P4
+pentiums), or through an x86 emulator (bochs or qemu). The resulting
+OS is available as a multiboot compliant ELF kernel (sos.elf) and as a
+floppy image (fd.img). It provides a very very very basic demo whose
+aim is to understand how everything works, not to animate sprites on
+the screen with 5:1 dolby sound.
+
+The initial technical features and lack-of-features of the OS are:
+ - monolithic kernel, fully interruptible, non-preemptible (big kernel
+ lock), target machines = i386 PC or better
+ - compiles on any host where the gcc/binutils toolchain (target
+ i586-gnu) is available. Can be tested on real i486/pentium
+ hardware, or on any host that can run an i486/pentium PC emulator
+ (bochs or qemu)
+ - kernel loaded by grub, or by a sample bootsector (up to article 2
+ ONLY)
+ - clear separation of physical memory and virtual memory concepts,
+ even inside the kernel: no identity-mapping of the physical memory
+ inside the kernel (allows to move virtual mappings of kernel pages
+ at run-time, eg to free ISA DMA pages, and to avercome the 4G RAM
+ barrier)
+ - slab-type kernel memory allocation
+ - no swap, no reverse mapping
+ - VERY simple drivers: keyboard, x86 video memory, IDE disks
+ - logical devices: partitions, FAT filesystem, "hard-coded"
+ mountpoints only (~ MSDOS)
+ - no network stack
+ - user-level features: ELF loader (no shared libraries), processes,
+ user threads (kernel-level scheduling only), mmap API, basic VFS
+
+To understand where to look at for what, here is a brief description:
+ - Makefile: the (ONLY) makefile of the OS. Targets are basically
+ 'all' and 'clean'
+ - bootstrap/ directory: code to load the kernel. Both the stuff
+ needed for a multiboot-compliant loader (eg grub) AND a bootsector
+ are provided. The bootsector may only be used up to article 2.
+ - sos/ directory: the entry routine for the kernel (main.c), various
+ systemwide header files, a set of common useful C routines
+ ("nano-klibc"), and kernel subsystems (kernel memory management,
+ etc...)
+ - hwcore/ directory: Low-level CPU- and kernel-related routines
+ (interrupt/exception management, translation tables and segment
+ registers, ...)
+ - drivers/ directory: basic kernel drivers for various (non CPU)
+ devices (keyboard, x86 video memory, bochs 0xe9 port, ...). Used
+ mainly for debugging
+ - support/ directory: scripts and configuration files to build the
+ floppy images
+ - extra/ directory: a set of configuration files to be customized for
+ non-x86 host installations (yes, we primarily develop SOS on a ppc, for
+ the x86 target of course), or for grub-less installations. See
+ README file in this directory.
+
+The code is licensed under the terms of the GNU GPL version 2 (see
+LICENSE file).
+
+Enjoy !
+
+ David Decotigny, Thomas Petazzoni, the Kos team
+ http://sos.enix.org/
+ http://david.decotigny.free.fr/
+ http://kos.enix.org/~thomas/
+ http://kos.enix.org/
+
+
+--
+David Decotigny
+
+PS: Made with a Mac.
diff --git a/sos-code-article3/VERSION b/sos-code-article3/VERSION
new file mode 100644
index 0000000..43273c3
--- /dev/null
+++ b/sos-code-article3/VERSION
@@ -0,0 +1,11 @@
+SOS -- Simple OS
+Copyright (C) 2003,2004 The SOS Team (David Decotigny & Thomas Petazzoni)
+
+Version "Article 3" -- Physical memory management & physical page allocator
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See the LICENSE file included in the distribution.
diff --git a/sos-code-article3/bootstrap/multiboot.S b/sos-code-article3/bootstrap/multiboot.S
new file mode 100644
index 0000000..4a7c65b
--- /dev/null
+++ b/sos-code-article3/bootstrap/multiboot.S
@@ -0,0 +1,74 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+
+/* The operating system is booted by Grub, so we almost have nothing
+ to do to boot it. We only have to conform to the Multiboot
+ standard, as defined by the Grub documentation */
+
+#define ASM 1
+/* The multiboot.h header contains a lot of multiboot standard
+ definitions */
+#include "multiboot.h"
+
+ /* The multiboot header itself. It must come first. */
+.section ".multiboot"
+ /* Multiboot header must be aligned on a 4-byte boundary */
+ .align 4
+multiboot_header:
+ /* magic= */ .long MULTIBOOT_HEADER_MAGIC
+ /* flags= */ .long MULTIBOOT_HEADER_FLAGS
+ /* checksum= */ .long -(MULTIBOOT_HEADER_MAGIC \
+ +MULTIBOOT_HEADER_FLAGS)
+ /* header_addr= */ .long multiboot_header
+ /* load_addr= */ .long __b_kernel
+ /* load_end_addr=*/ .long __e_load
+ /* bss_end_addr= */ .long __e_kernel
+ /* entry_addr= */ .long multiboot_entry
+
+/* Here is the beginning of the code of our operating system */
+.text
+
+.globl start, _start
+start:
+_start:
+multiboot_entry:
+ /* Set up a stack */
+ movl $(stack + MULTIBOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Set EFLAGS to 0 */
+ pushl $0
+ /* pop stack into the EFLAGS register */
+ popf
+
+ /* Push the magic and the address on the stack, so that they
+ will be the parameters of the cmain function */
+ pushl %ebx
+ pushl %eax
+
+ /* Call the cmain function (os.c) */
+ call EXT_C(sos_main)
+
+ /* Should never get there */
+loop:
+ hlt
+ jmp loop
+
+ /* Here is the stack */
+.comm stack, MULTIBOOT_STACK_SIZE
diff --git a/sos-code-article3/bootstrap/multiboot.h b/sos-code-article3/bootstrap/multiboot.h
new file mode 100644
index 0000000..bee676d
--- /dev/null
+++ b/sos-code-article3/bootstrap/multiboot.h
@@ -0,0 +1,129 @@
+#ifndef __MULTIBOOT_H__
+#define __MULTIBOOT_H__
+
+/* multiboot.h - the header for Multiboot */
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Macros. */
+
+/* The magic number for the Multiboot header. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* The flags for the Multiboot header. */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* The magic number passed by a Multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (16KB). */
+#define MULTIBOOT_STACK_SIZE 0x4000
+
+#define MULTIBOOT_CMDLINE 4
+#define MULTIBOOT_MODS 8
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* Do not include here in boot.S. */
+
+
+
+/* Types. */
+
+/* The Multiboot header. */
+typedef struct multiboot_header
+{
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* The symbol table for a.out. */
+typedef struct aout_symbol_table
+{
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* The section header table for ELF. */
+typedef struct elf_section_header_table
+{
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* The Multiboot information. */
+typedef struct multiboot_info
+{
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union
+ {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+ unsigned long drives_length;
+ unsigned long drives_addr;
+} multiboot_info_t;
+
+/* The module structure. */
+typedef struct module
+{
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* The memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map
+{
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+void dump_multiboot_info(multiboot_info_t *mbi);
+
+#endif /* ! ASM */
+
+#endif /* __MULTIBOOT_H__ */
diff --git a/sos-code-article3/drivers/bochs.c b/sos-code-article3/drivers/bochs.c
new file mode 100644
index 0000000..db18599
--- /dev/null
+++ b/sos-code-article3/drivers/bochs.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <hwcore/ioports.h>
+#include <sos/klibc.h>
+
+#include "bochs.h"
+
+/* This is a special hack that is only useful when running the
+ operating system under the Bochs emulator. */
+#define SOS_BOCHS_IOPORT 0xe9
+
+sos_ret_t sos_bochs_setup(void)
+{
+ return SOS_OK;
+}
+
+
+#define sos_bochs_putchar(chr) \
+ outb((chr), SOS_BOCHS_IOPORT)
+
+sos_ret_t sos_bochs_putstring(const char* str)
+{
+ for ( ; str && (*str != '\0') ; str++)
+ sos_bochs_putchar(*str);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes)
+{
+ unsigned c;
+
+#define BOCHS_PRTHEX(q) \
+ ({ unsigned char r; if ((q) >= 10) r='a'+(q)-10; \
+ else r='0'+(q); sos_bochs_putchar(r); })
+
+ switch (nbytes)
+ {
+ case 4:
+ c = (val >> 24) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 3:
+ c = (val >> 16) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 2:
+ c = (val >> 8) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 1:
+ c = val & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes)
+{
+ int offs;
+ for (offs = 0 ; offs < nbytes ; offs++)
+ {
+ const unsigned char *c;
+
+ if ((offs % 16) == 0)
+ {
+ sos_bochs_putstring("0x");
+ sos_bochs_puthex(offs, 4);
+ }
+
+ if ((offs % 8) == 0)
+ sos_bochs_putstring(" ");
+
+ c = (const unsigned char*)(addr + offs);
+ sos_bochs_puthex(*c, 1);
+ sos_bochs_putstring(" ");
+
+ if (((offs + 1) % 16) == 0)
+ sos_bochs_putstring("\n");
+ }
+
+ if (offs % 16)
+ sos_bochs_putstring("\n");
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_bochs_putstring(buff);
+}
diff --git a/sos-code-article3/drivers/bochs.h b/sos-code-article3/drivers/bochs.h
new file mode 100644
index 0000000..310b023
--- /dev/null
+++ b/sos-code-article3/drivers/bochs.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_BOCHS_H_
+#define _SOS_BOCHS_H_
+
+/**
+ * @file bochs.h
+ *
+ * If you compiled Bochs with the --enable-e9-hack, then any character
+ * printed to the 0xE9 I/O port is printed to the xterm that is
+ * running Bochs. This may appear to be a detail, but in fact, this
+ * functionnality is *VERY* precious for debugging purposes. This
+ * """driver""" handles this feature.
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+
+sos_ret_t sos_bochs_setup(void);
+
+sos_ret_t sos_bochs_putstring(const char* str);
+
+/** Print the least signficant 32 (nbytes == 4), 24 (nbytes == 3), 16
+ (nbytes == 2) or 8 (nbytes == 1) bits of val in hexadecimal. */
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes);
+
+/** hexdump-style pretty printing */
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#endif
diff --git a/sos-code-article3/drivers/x86_videomem.c b/sos-code-article3/drivers/x86_videomem.c
new file mode 100644
index 0000000..cc4b79c
--- /dev/null
+++ b/sos-code-article3/drivers/x86_videomem.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <sos/klibc.h>
+#include <hwcore/ioports.h>
+
+#include "x86_videomem.h"
+
+/* The text video memory starts at address 0xB8000. Odd bytes are the
+ ASCII value of the character, even bytes are attribute for the
+ preceding character. */
+#define VIDEO 0xb8000
+
+
+/* Console screen size */
+#define LINES 25
+#define COLUMNS 80
+
+
+/** The structure of a character element in the video memory. @see
+ http://webster.cs.ucr.edu/AoA DOS edition chapter 23 */
+typedef struct {
+ unsigned char character;
+ unsigned char attribute;
+} __attribute__ ((packed)) x86_video_mem[LINES*COLUMNS];
+
+
+
+/** The base pointer for the video memory */
+static volatile x86_video_mem *video = (volatile x86_video_mem*)VIDEO;
+
+sos_ret_t sos_x86_videomem_setup(void)
+{
+ /*
+ * Hide cursor. @see Ralf Brown's interrupt (and port) list
+ * http://www-2.cs.cmu.edu/~ralf/files.html
+ */
+#define CRT_REG_INDEX 0x3d4
+#define CRT_REG_DATA 0x3d5
+
+ /* CRT index port => ask for access to register 0xa ("cursor
+ start") */
+ outb(0x0a, CRT_REG_INDEX);
+
+ /* (RBIL Tables 708 & 654) CRT Register 0xa => bit 5 = cursor OFF */
+ outb(1 << 5, CRT_REG_DATA);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute)
+{
+ /* Clears the screen */
+ int i;
+ for(i = 0 ; i < LINES*COLUMNS ; i++)
+ {
+ (*video)[i].character = 0;
+ (*video)[i].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ for ( ; str && *str && (video_offs < LINES*COLUMNS) ; str++, video_offs++)
+ {
+ (*video)[video_offs].character = (unsigned char)*str;
+ (*video)[video_offs].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ (*video)[video_offs].character = c;
+ (*video)[video_offs].attribute = attribute;
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_x86_videomem_putstring(row, col, attribute, buff);
+}
diff --git a/sos-code-article3/drivers/x86_videomem.h b/sos-code-article3/drivers/x86_videomem.h
new file mode 100644
index 0000000..31a9dfc
--- /dev/null
+++ b/sos-code-article3/drivers/x86_videomem.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_X86_VIDEOMEM_H_
+#define _SOS_X86_VIDEOMEM_H_
+
+/**
+ * @file x86_videomem.h
+ *
+ * On x86 PC platforms, the text mode screen memory (and CGA/EGA/VGA
+ * too) is mapped into physical memory. This file handles access to
+ * this screen, supposed to be set in text-mode, through this memory
+ * area. All the functions below print the characters directly to the
+ * memory, without interpreting the escaped characters (such as \n,
+ * \r...)
+ */
+
+#include <sos/errno.h>
+
+/**
+ * x86 video attributes
+ * See http://webster.cs.ucr.edu/AoA/DOS/ch23/CH23-1.html
+ */
+/* Normal and Dark/Light foreground */
+#define SOS_X86_VIDEO_FG_BLACK 0
+#define SOS_X86_VIDEO_FG_DKGRAY 8
+#define SOS_X86_VIDEO_FG_BLUE 1
+#define SOS_X86_VIDEO_FG_LTBLUE 9
+#define SOS_X86_VIDEO_FG_GREEN 2
+#define SOS_X86_VIDEO_FG_LTGREEN 10
+#define SOS_X86_VIDEO_FG_CYAN 3
+#define SOS_X86_VIDEO_FG_LTCYAN 11
+#define SOS_X86_VIDEO_FG_RED 4
+#define SOS_X86_VIDEO_FG_LTRED 12
+#define SOS_X86_VIDEO_FG_MAGENTA 5
+#define SOS_X86_VIDEO_FG_LTMAGENTA 13
+#define SOS_X86_VIDEO_FG_BROWN 6
+#define SOS_X86_VIDEO_FG_YELLOW 14
+#define SOS_X86_VIDEO_FG_LTGRAY 7
+#define SOS_X86_VIDEO_FG_WHITE 15
+/* Background */
+#define SOS_X86_VIDEO_BG_BLACK (0 << 4)
+#define SOS_X86_VIDEO_BG_BLUE (1 << 4)
+#define SOS_X86_VIDEO_BG_GREEN (2 << 4)
+#define SOS_X86_VIDEO_BG_CYAN (3 << 4)
+#define SOS_X86_VIDEO_BG_RED (4 << 4)
+#define SOS_X86_VIDEO_BG_MAGENTA (5 << 4)
+#define SOS_X86_VIDEO_BG_BROWN (6 << 4)
+#define SOS_X86_VIDEO_BG_LTGRAY (7 << 4)
+/* Blinking */
+#define SOS_X86_VIDEO_FG_BLINKING (1 << 7)
+
+
+/** Setup the video RAM mapping and clear the screen */
+sos_ret_t sos_x86_videomem_setup(void);
+
+/** Clears the screen and set the background color as given by
+ attribute */
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute);
+
+/** Print the string on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str);
+
+/** Print the character on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+ __attribute__ ((format (printf, 4, 5)));
+
+#endif /* _SOS_X86_VIDEOMEM_H_ */
diff --git a/sos-code-article3/extra/Makefile b/sos-code-article3/extra/Makefile
new file mode 100644
index 0000000..f858aa6
--- /dev/null
+++ b/sos-code-article3/extra/Makefile
@@ -0,0 +1,40 @@
+OBJCOPY=objcopy
+
+all: sos_qemu.img
+
+-include ../.mkvars
+
+# The image is the simple concatenation of the boot sector and the kernel
+# It may be use in bochs or on a real floppy, but NOT in qemu (see below)
+sos_bsect.img: bsect.bin sos.bin
+ cat $^ > $@
+ @echo "You can use the $@ image in bochs or on a real floppy (NOT qemu)"
+
+# For qemu, the trick is to tell it we have *more* than 1440 sectors (720kB).
+# Rtherwise the qemu disk geometry will be configured to be that of a 720kB
+# floppy, while our boot sector assumes it to be 1.44MB
+sos_qemu.img: sos_bsect.img
+ # Padding with 0s after the bsect/kernel image
+ cat $< /dev/zero | dd of=$@ bs=1k count=1440
+ @echo "You can use the $@ image in qemu, bochs, or on a real floppy"
+
+# we extract the boot sector from the main ELF binary
+bsect.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -j .bootsect $< $@
+
+# we extract the kernel code from the main ELF binary
+sos.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -R .bootsect $< $@
+
+# The main ELF binary contains the boot sector and the kernel code
+# linked together (hence we deal with a SINGLE image that we split
+# above) because they share some symbol definitions
+sos_bsect.elf: bootsect.o compile_kernel
+ $(LD) --warn-common -T ./sos_bsect.lds -o $@ \
+ bootsect.o $(wildcard ../hwcore/*.o ../drivers/*.o ../sos/*.o)
+
+compile_kernel:
+ $(MAKE) -C ..
+
+clean:
+ $(RM) *.img *.elf *.bin *~ *.o *.out
diff --git a/sos-code-article3/extra/README b/sos-code-article3/extra/README
new file mode 100644
index 0000000..0272f1f
--- /dev/null
+++ b/sos-code-article3/extra/README
@@ -0,0 +1,73 @@
+
+Contents of the extra/ directory
+================================
+
+Data and configuration files to support generation of sos on non-x86
+and/or grub-less hosts:
+ - dot.mkvars: file to copy as .mkvars in the root directory to
+ compile on a non-x86 host, and to generate the grub floppy image on
+ a grub-less host
+ - grub.img.gz: compressed image of a Grub floppy (without any
+ kernel). Used by dot.mkvars.
+ - mtoolsrc: file needed by .mkvars to compile a the floppy image
+
+Support of a sos-specific boot sector:
+ - Makefile: rules to compile sos_bsect.img, the floppy image with the
+ boot sector and the Sos
+ - bootsect.S: x86 Sos boot sector (GNU as). Depends on sos_bsect.lds
+ - sos_bsect.lds: ld script to bind the boot sector with the remaining
+ of the kernel
+
+Misc:
+ - qemu-port-e9.diff: patch over qemu to support the bochs "port 0xe9 hack"
+
+
+What you can do with these files
+================================
+
+
+*** Compile SOS from another architecture:
+------------------------------------------
+ - compile a cross-compiler for the i586-gnu target. This involves
+ compiling the binutils and gcc. Here are example configuration
+ options for them:
+ binutils (replace sparc-cun-solaris with your arch):
+ ../binutils-2.13/configure --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/binutils-2.11 --host=sparc-sun-solaris2.7 i586-gnu
+ make && make install
+ gcc (ditto):
+ CFLAGS="-O2 -Dinhibit_libc" ../gcc-3.2/configure --target=i586-gnu --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/gcc-3.2 --with-as=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/as --with-ld=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/ld --with-gnu-as --with-gnu-ld --enable-languages=c --disable-shared --disable-multilib --disable-nls --enable-threads=single
+ make && make install
+ - compile the mtools
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS from an x86 where grub is not or incorrectly installed:
+--------------------------------------------------------------------------
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS with its own bootloader:
+-------------------------------------------
+ - for cross-architecture compilation: see above
+ - cd to this extra/ directory
+ - run 'make'
+ - the floppy image is: sos_bsect.img
+ NOTE : SOS will not boot correctly this way after article 2 !
+
+
+--
+David Decotigny
diff --git a/sos-code-article3/extra/bootsect.S b/sos-code-article3/extra/bootsect.S
new file mode 100644
index 0000000..f01ca20
--- /dev/null
+++ b/sos-code-article3/extra/bootsect.S
@@ -0,0 +1,393 @@
+
+/*
+ * @(#) $Id: bootsect.S,v 1.6 2004/06/18 07:43:51 d2 Exp $
+ * Description : Bootsecteur en syntaxe AT&T
+ * Auteurs : Thomas Petazzoni & Fabrice Gautier & Emmanuel Marty
+ * Jerome Petazzoni & Bernard Cassagne & coffeeman
+ * David Decotigny
+ * Bug reports to kos-misc@enix.org
+ */
+
+/*
+ * But global de ce bootsecteur :
+ *
+ * - Initialiser la becane
+ * - Charger le kernel
+ * - Passer en mode protege
+ * - Executer le kernel
+ *
+ * Taille restante : Je vous rappelle qu'un bootsecteur ne peut faire
+ * qu'au maximum 512 octets dont 2 octets obligatoires 0xAA55. Sur
+ * les 510 octets reellement utilisables, il reste 3 octets dispo (60
+ * si on decide d'enlever le BPB un jour) !!!
+ *
+ * thomas_petazzoni : - detection des codes d'erreurs de chargement
+ * David_Decotigny : - Passage en GNU as
+ * David_Decotigny : - Chargement du noyau au-dela du 1er Mega (taille
+ * max = 0x9e000 octets = 632ko), pour avoir le
+ * meme noyau sous grub et avec le bootsecteur
+ */
+
+ /*
+ * Sequence d'operations :
+ * - Le BIOS charge le bootsect en 0x7c00 (BOOT_ADRESS). On choisit
+ * la representation 0x7c0:0000 pour que le .org 0 reste valide
+ * - Le bootsect se deplace de lui-meme en 0x9f000 (COPY_ADRESS). On
+ * choisit la representation 0x9f00:0000 pour que le .org 0 reste
+ * valide
+ * - Le bootsect verifie que le processeur est du type 386+
+ * - Il charge le noyau depuis la disquette en memoire a partir de
+ * 0x1000 (LOAD_ADRESS). Le noyau peut au max tenir sur
+ * SECTORS_TO_LOAD secteurs
+ * - Il passe en pmode flat (apres ouverture a20)
+ * - Il recopie le noyau (situe en LOAD_ADRESS) vers son adresse
+ * finale (FINAL_ADDRESS = 2Mo). La recopie se fait sur tout l'espace
+ * LOAD_ADRESS ---> COPY_ADRESS, c'est a dire sur 0x9e000 octets =
+ * 632ko. Le noyau peut donc au max faire 632ko. Le nombre max de
+ * secteurs de disquette qu'on peut charger est donc 1264
+ */
+
+
+/* La taille de la pile */
+#define BOOT_STACK_SIZE 0x4000
+
+ .file "bootsect.S"
+
+ /* Tout est place dans une seule section */
+ .section ".bootsect"
+
+ /* L'essentiel du bootsector (sauf les 1eres instructions)
+ sont a un offset 0. On fait en sorte que le compilo soit
+ d'accord la-dessus. Quand on a des adresse realm exotiques
+ (0x7c00, 0x9f000, ...), on s'arrange toujours pour avoir un
+ offset de 0 => on choisira le segment adapte (0x7c0,
+ 0x9f00, ...). Il ne faut pas oublier le ld -Ttext 0 */
+ .org 0
+
+ /* Pour que gas genere du 16bits, afin que ca marche en realm */
+ .code16
+
+#define SECTORS_TO_LOAD 128 /* 64 ko */ /* MAX=1264 */
+
+/*
+ * Parametres de la disquette. Comme c'est chiant de faire une
+ * procedure de detection auto, et que ca prend de la place, on fait
+ * ca "a la main". Par exemple, une DD 720 Ko a 9 secteurs/piste, une
+ * 1.44 Mo a 18 secteurs/pistes
+ */
+#define CYLS 80
+#define HEADS 1
+#define SECTS 18
+
+#define BOOT_ADRESS 0x07C00 /* Adresse de demarrage (lineaire) */
+#define BOOT_SEG (BOOT_ADRESS>>4) /* Segment de Boot */
+#define BOOT_SIZE 512 /* Taille bu bootsecteur */
+#define COPY_ADRESS 0x9F000 /* La ou on va copier le
+ bootsecteur (lineaire) */
+#define COPY_SEG (COPY_ADRESS>>4) /* Segment de la ou on va
+ copier le bootsecteur */
+#define LOAD_ADRESS 0x01000 /* 1er chargement du systeme */
+#define LOAD_SEG (LOAD_ADRESS>>4) /* Segment du 1er chargement du */
+#define MAX_KERN_LEN COPY_ADRESS-LOAD_ADRESS /* Taille noyau maxi */
+
+/* IMPORTANT : Cette valeur DOIT etre identique a l'adresse presente
+ dans sos.lds ! */
+#define FINAL_ADDRESS 0x200000 /* Adresse finale (physique de 0 a 4G)
+ ou est charge le noyau */
+
+#define OP16 .byte 0x66 ;
+#define OP32 .byte 0x66 ;
+
+/*
+ * Procedure qui vide le buffer clavier.
+ */
+#define WAITKB \
+ 1: ;\
+ .word 0xeb ;\
+ .word 0xeb ;\
+ inb $0x64, %al ;\
+ andb $0x2, %al ;\
+ jnz 1b
+
+ /* Le point d'entree dans le bootsect */
+.globl _bsect
+_bsect:
+
+ /*
+ * La portion qui suit est situee a un offset 0x7c00 en
+ * memoire. Attention donc aux references memoire dans cette
+ * partie. On choisit de rester en offset 0 (.org 0), mais on
+ * charge correctement les segments a 0x7c0.
+ */
+
+ movw $BOOT_SEG, %ax /* le bootsecteur est a 0x7C00 en lineaire */
+ movw %ax, %ds /* on le copie a l'adresse COPY_ADRESS */
+ xorw %si, %si /* comme cette adresse est la plus haute de la mem */
+ xorw %di, %di /* on pourra charger un kernel + gros */
+ movw $(BOOT_SIZE>>1), %cx
+ movw $COPY_SEG, %ax
+ movw %ax, %es
+ cld
+ rep ; movsw
+
+ /* on continue a executer le bootsecteur, mais maintenant a
+ partir de 0x9F000, qu'on represente sous la forme
+ 0x9f00:offset */
+ ljmp $COPY_SEG, $here
+
+ /*
+ * A partir de maintenant, on est a un offset 0 en memoire
+ * (segment 0x9f00), conformement a ce que veut le compilo.
+ */
+here:
+ movw %ax, %ds
+
+ /* Petite pile temporaire (1k - 3.84k en RAM ; les adresses 0-1k
+ correspondent au vecteur d'interruptions). */
+ movw %ax, %ss
+ movw $(LOAD_ADRESS - 0x10), %sp
+
+ /* Efface l'ecran */
+ movb $0x0, %ah
+ movb $0x3, %al
+ int $0x10
+
+ /* Affiche les messages d'attente */
+ movw $loadkern, %si
+ call message
+ movw $check, %si
+ call message
+
+check386:
+ /*
+ * la attention, plus complexe : on teste si le proc est un
+ * 386+ pour cela, on va essayer de modifier les bits 12 ? 14
+ * du registre E-flag si la modification reste, alors le proc
+ * est un 386+, sinon, c'est =< 286
+ *
+ * Merci a Emmanuel Marty pour la compatibilite avec les 386
+ * "pre-jurassique"
+ */
+
+ pushf /* on sauvegarde le E-Flag */
+ movb $0x70, %ah
+ pushw %ax
+ popf
+ pushf
+ popw %ax
+ orb %ah, %ah
+ je no386 /* si la modif n'est pas valable, alors on saute a
+ no386 */
+ popf /* on les restaure ? la fin ... */
+
+ /* Message de confirmation de 386+ et d'attente */
+ movw $found386, %si
+ call message
+ movw $loading, %si
+ call message
+
+/* Copie du noyau disquette => RAM a partir de 0x1000
+ L'adresse de destination est définie par es:0, où es vaut
+ initialement 0x100 (ie correspond alors à l'adresse 256*16, soit 4
+ ko). Chaque itération incrémente ce registre es de 32, ce qui
+ correspond à un bond de 32*16 en mémoire, soit la taille d'un
+ secteur. De cette façon, puisqu'on joue sur les segments plutôt que
+ sur les offsets, la taille du noyau n'est pas limitée à 64 ko. Elle
+ est limitée par contre à la taille de la mémoire disponible sous
+ les 1Mo, \ie 640 ko (0x9f000 - 0x1000). */
+copyKernel:
+ /* Chargement du noyau en LOAD_SEG:0 */
+ /* 3 iterateurs :
+ - load_size : le nbre de secteurs a charger
+ - cl : le secteur ou on en est pour le
+ cylindre en cours (<= SECTS)
+ - dh : la tete en cours (0/1)
+ */
+ movb $0, %dl
+ movw $LOAD_SEG, %ax
+ movw %ax, %es
+
+ xorw %bx, %bx
+ xorw %dx, %dx
+ movw $1, %cx /* premier secteur */
+
+.nextsector: /* prochain secteur */
+ incb %cl /* en incrementant CL */
+ cmpb $SECTS, %cl /* si CL =< SECTS (=nbre de secteurs/pistes)
+ alors on charge */
+ jbe .sector
+ movb $1, %cl /* sinon on revient au secteur 1 */
+ incb %dh /* mais sur l'autre tete */
+ cmpb $1, %dh /* on recompare, si DH =< 1 */
+ je .sector /* on charge */
+ movb $0, %dh /* sinon on repasse a la tete 0 */
+ incb %ch /* mais on change de cylindre */
+
+.sector:
+ pushw %es
+ movw $0x0201, %ax /* service 0x2, chargement 0x1 seecteur */
+ int $0x13 /* Go ! */
+ jc halt /* erreur */
+ popw %ax
+ addw $32, %ax /* on a charge un secteur, donc on doit
+ charger 512 bytes plus loin */
+ movw %ax, %es /* on avance donc le segment du buffer de
+ 32bytes, ie 1 secteur en RAM (car 32*16=512) */
+
+ movw $(0x0E*256+'.'), %ax /* affiche un point */
+ int $0x10
+
+ decw (load_size) /* et on repart pour le prochain secteur
+ tant qu'on n'a pas fini ! */
+ jnz .nextsector
+
+after:
+ movw $0x03f2, %dx
+ inb %dx, %al /* stoppe le moteur */
+ andb $0x0f, %al
+ outb %al, %dx
+
+ cli /* on interdit les interruptions */
+
+fincopie:
+ pushw %cs
+ popw %ds
+
+ /* on ouvre la porte A20 */
+ WAITKB /* on vide le buffer */
+ movb $0xd1, %al /* on met a jour le port */
+ outb %al, $0x64
+ WAITKB
+ movb $0xdf, %al /* bit 2 = ouverture/fermeture */
+ outb %al, $0x60
+
+ /*
+ * init gdt
+ */
+InitGDT:
+ /* Préparation du flat mode */
+ lgdt gdtr
+
+GoPMode:
+ /* Passage en mode protégé */
+ movl %cr0, %eax
+ orb $1, %al /* set PE bit to 1 */
+ movl %eax, %cr0
+
+ /* we are not yet in Pmode jump 'in' pmode clearing prefetch
+ * queue and loading a new selector */
+ movw $0x10, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+/*
+ * Code 32 bits ============================================================
+ */
+ .code32
+
+JumpToHere32: /* Se deplace a l'endroit actuel, en passant en 32bits
+ et en utilisant la gdt, et vide la prefetch queue */
+ .byte 0x66 /* Prefixe 32bits : en realite, jusqu'au jmp, on est
+ encore en 16 bits */
+ ljmp $0x8, $(COPY_ADRESS+(Here32))
+Here32:
+ /* Et voila : On est en 32 bits vrai */
+
+MoveKernelToFinalAddr: /* Deplace le noyau (en LOAD_ADDRESS) vers sa
+ destination finale (FINAL_ADDRESS) */
+ movl $0x10, %eax
+ movl %eax, %ds /* Seg Src = DSeg */
+ movl %eax, %es /* Sed Dest = DSeg */
+ cld
+ movl $LOAD_ADRESS, %esi /* On commence la copie au debut du noyau */
+ movl $FINAL_ADDRESS, %edi /* On copie vers cette adresse */
+ movl $MAX_KERN_LEN, %ecx /* Taille recopie */
+ shrl $2, %ecx
+ rep
+ movsl
+
+LaunchKernel:
+ /* Met en place une pile au niveau du symbole "stack" */
+ movl %eax, %ss
+ movl $(stack + BOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Saut vers le noyau. La GDT est en place (flat mode), les
+ * selecteurs aussi, a20 est ouverte, et les interruptions sont
+ * cli + pas de idt. Le PIC n'est pas programme */
+ ljmp $0x8, $sos_main
+
+/*
+ * Utilities ============================================================
+ */
+ .code16
+
+message:
+ lodsb /* charge ds:si dans al et incremente si */
+ orb %al, %al /* si al = 0 */
+ jz 1f
+ movb $0x0e, %ah /* service 0Eh (affichage d'un caractere) */
+ movw $0x0007, %bx /* Parametres : blanc sur fond noir */
+ int $0x10 /* Appel de l'interruption 10h */
+ jmp message /* On repart au début ... */
+ 1: ret /* si la chaine est finie alors on retourne
+ dans la fonction appelante */
+
+halt:
+ pushw %cs
+ popw %es
+ movw $haltmsg, %si
+ call message
+ cli
+ 1: jmp 1b
+ ret
+
+no386:
+ movw $need386, %si
+ call message
+ call halt
+
+ /*
+ * GDT
+ */
+
+gdt:
+gdtr:
+NULL_Desc:
+ .word (EndGDT)-(gdt)-1 /* Taille GDT */
+ .long (gdt)+COPY_ADRESS
+unused:
+ .word 0
+
+CS_Desc: /* 0x8 */
+ .word 0xFFFF, 0
+ .byte 0, 0x9B, 0xCF, 0
+
+DS_Desc: /* 0x10 */
+ .word 0xFFFF, 0
+ .byte 0, 0x93, 0xCF, 0
+
+EndGDT:
+
+ /* quelques messages */
+
+loadkern: .string "-= S O S =- : The Simple Operating System \r\n"
+check: .string "Checking for a 386+ processor... "
+found386: .string " [OK]\r\n"
+need386: .string " [FAILED]\r\n"
+diskerror: .string "Disk Error\r\n"
+loading: .string "Loading... "
+haltmsg: .string "System Halted\r\n"
+
+/*** Les code/données du boot secteur se terminent ICI. le marqueur de
+ * fin (aa55) est ajouté automatiquement par le script ld
+ * sos_bsect.lds ***/
+
+/* La pile de 16k qu'on utilise au niveau de LaunchKernel se trouve
+ declaree avec le noyau, dans sa section ".bss", cad HORS du boot
+ secteur ! (sinon ca depasserait 512B, forcément). On aurait pu la
+ définir directement dans le sos_bsect.lds, ou dans un fichier .c
+ auxiliaire pour plus de clarté */
+.comm stack, BOOT_STACK_SIZE
diff --git a/sos-code-article3/extra/dot.mkvars b/sos-code-article3/extra/dot.mkvars
new file mode 100644
index 0000000..1f7dca5
--- /dev/null
+++ b/sos-code-article3/extra/dot.mkvars
@@ -0,0 +1,29 @@
+# For cross-compilation and/or installations without grub available,
+# copy this file as .mkvars to the root directory of the SOS sources,
+# and customize the CC/LD/... variables. You still need the mtools
+# installed and running
+
+CC := i586-gnu-gcc
+LD := i586-gnu-ld
+OBJCOPY := i586-gnu-objcopy
+CFLAGS += -O3
+
+# Configuration of mtools
+MTOOLSRC = extra/mtoolsrc
+export MTOOLSRC
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ) menu.txt
+ gzip -dc < extra/grub.img.gz > $@
+ mcopy menu.txt v:/boot/grub/
+ mmd v:/system
+ mcopy sos.elf v:/system/sos.elf
+
+menu.txt:
+ echo timeout 0 > $@
+ echo default 0 >> $@
+ echo title SOS >> $@
+ echo "root (fd0)" >> $@
+ echo kernel /system/sos.elf >> $@
+
+runbochs: all
+ echo c | bochs -q
diff --git a/sos-code-article3/extra/grub.img.gz b/sos-code-article3/extra/grub.img.gz
new file mode 100644
index 0000000..4f98e74
--- /dev/null
+++ b/sos-code-article3/extra/grub.img.gz
Binary files differ
diff --git a/sos-code-article3/extra/mtoolsrc b/sos-code-article3/extra/mtoolsrc
new file mode 100644
index 0000000..df1a26e
--- /dev/null
+++ b/sos-code-article3/extra/mtoolsrc
@@ -0,0 +1,2 @@
+# For older versions of mtools, you may have to remove "filter"
+drive v: file="fd.img" 1.44M filter
diff --git a/sos-code-article3/extra/qemu-port-e9.diff b/sos-code-article3/extra/qemu-port-e9.diff
new file mode 100644
index 0000000..d8be044
--- /dev/null
+++ b/sos-code-article3/extra/qemu-port-e9.diff
@@ -0,0 +1,73 @@
+--- Makefile.target 17 Mar 2004 23:46:04 -0000 1.19
++++ Makefile.target 18 Mar 2004 14:20:29 -0000
+@@ -217,7 +217,8 @@
+ # must use static linking to avoid leaving stuff in virtual address space
+ VL_OBJS=vl.o osdep.o block.o monitor.o \
+ ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
+- fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
++ fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o \
++ port-e9.o
+ ifeq ($(TARGET_ARCH), ppc)
+ VL_OBJS+= hw.o
+ endif
+--- hw/pc.c 14 Mar 2004 21:46:48 -0000 1.2
++++ hw/pc.c 18 Mar 2004 14:20:29 -0000
+@@ -371,6 +371,7 @@
+ SB16_init();
+
+ fdctrl_init(6, 2, 0, 0x3f0, fd_table);
++ port_e9_init();
+
+ cmos_init(ram_size, boot_device);
+ }
+--- /dev/null 2003-01-30 11:24:37.000000000 +0100
++++ port-e9.c 2004-03-18 15:18:52.660493187 +0100
+@@ -0,0 +1,38 @@
++/*
++ * QEMU Port 0xe9 hack
++ *
++ * Copyright (c) 2000-2004 E. Marty, the bochs team, D. Decotigny
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++ * THE SOFTWARE.
++ */
++#include <stdio.h>
++#include <unistd.h>
++#include <inttypes.h>
++
++#include "vl.h"
++
++static void bochs_e9_write(void *opaque, uint32_t address, uint32_t data)
++{
++ write(fileno(stdout), &data, 1);
++}
++
++void port_e9_init ()
++{
++ register_ioport_write(0xe9, 1, 1, bochs_e9_write, NULL);
++}
+--- vl.h 17 Mar 2004 23:17:16 -0000 1.14
++++ vl.h 18 Mar 2004 14:29:06 -0000
+@@ -268,4 +268,7 @@
+ void term_flush(void);
+ void term_print_help(void);
+
++/* port-e9.c */
++void port_e9_init(void);
++
+ #endif /* VL_H */
diff --git a/sos-code-article3/extra/sos_bsect.lds b/sos-code-article3/extra/sos_bsect.lds
new file mode 100644
index 0000000..ac42f23
--- /dev/null
+++ b/sos-code-article3/extra/sos_bsect.lds
@@ -0,0 +1,61 @@
+/* Copyright (C) 2004, David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+SECTIONS
+{
+ /* ***********************************************
+ * The bootsector is here. We link it against the remaining of the kernel
+ * in order to automatically figure out its size that must be loaded
+ * from file to memory (see the load_size definition below)
+ */
+
+ /* If we use one, we put the boot sector here. We don't set its
+ * address to 0x7c000 (aka 0x7c00:0), since it reloads itself to
+ * 0x9f000, causing the 0x7c000 address to be meaningless too. So we
+ * chose to pretend that the address is 0x0, and to make a little
+ * address arithmetic in bootsect.S */
+ .bootsect 0x0 :
+ {
+ /* The code for the boot sector goes here */
+ *(.bootsect);
+
+ /* The load_size symbol contains the size of the area (in
+ * sectors, aka 512 Bytes) that the boot sector should copy from
+ * the disk. The bss section is not included since it uses 0
+ * bytes on disk */
+ load_size = .;
+ LONG((__e_load - __b_load + 511) >> 9);
+ /* ---> This is equivalent to ceil( (__e_load - __b_load) / 512 ) */
+
+ /* At offsets 511 and 512, we set the boot sector signature (AA55h) */
+ . = 0x1fe;
+ SHORT(0xAA55);
+ }
+}
+
+
+/* This is to avoid a cut/paste here. Please notice that a multiboot
+ * section WILL be inserted, which is NOT mandatory (we could have
+ * removed it without getting into trouble). Please note however that
+ * the *.bin files will NOT be multiboot compatible (they are not in ELF
+ * format): they are expected to be directly booted by the BIOS (or
+ * by the "chainloader" command of Grub). */
+INCLUDE ../support/sos.lds
+
+/* We overload the entry set in sos.lds, just to avoid an ld warning */
+ENTRY(sos_main);
diff --git a/sos-code-article3/hwcore/exception.c b/sos-code-article3/hwcore/exception.c
new file mode 100644
index 0000000..9ab5aff
--- /dev/null
+++ b/sos-code-article3/hwcore/exception.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "idt.h"
+#include "irq.h"
+
+#include "exception.h"
+
+/* array of exception wrappers, defined in exception_wrappers.S */
+extern sos_vaddr_t sos_exception_wrapper_array[SOS_EXCEPT_NUM];
+
+/* arrays of exception handlers, shared with exception_wrappers.S */
+sos_exception_handler_t sos_exception_handler_array[SOS_EXCEPT_NUM] =
+ { NULL, };
+
+sos_ret_t sos_exceptions_setup(void)
+{
+ /* We inidicate that the double fault exception handler is defined,
+ and give its address. this handler is a do-nothing handler (see
+ exception_wrappers.S), and it can NOT be overriden by the
+ functions below */
+ return sos_idt_set_handler(SOS_EXCEPT_BASE + SOS_EXCEPT_DOUBLE_FAULT,
+ (sos_vaddr_t) sos_exception_wrapper_array[SOS_EXCEPT_DOUBLE_FAULT],
+ 0 /* CPL0 routine */);
+}
+
+
+sos_ret_t sos_exception_set_routine(int exception_number,
+ sos_exception_handler_t routine)
+{
+ sos_ret_t retval;
+ sos_ui32_t flags;
+
+ if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM))
+ return -SOS_EINVAL;
+
+ /* Double fault not supported */
+ if (exception_number == SOS_EXCEPT_DOUBLE_FAULT)
+ return -SOS_ENOSUP;
+
+ sos_disable_IRQs(flags);
+
+ retval = SOS_OK;
+
+ /* Set the exception routine to be called by the exception wrapper */
+ sos_exception_handler_array[exception_number] = routine;
+
+ /* If the exception is to be enabled, update the IDT with the exception
+ wrapper */
+ if (routine != NULL)
+ retval
+ = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number,
+ (sos_vaddr_t) sos_exception_wrapper_array[exception_number],
+ 0 /* CPL0 routine */);
+ else /* Disable the IDT entry */
+ retval
+ = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number,
+ (sos_vaddr_t)NULL /* No routine => disable IDTE */,
+ 0 /* don't care */);
+
+ sos_restore_IRQs(flags);
+ return retval;
+}
+
+
+sos_exception_handler_t sos_exception_get_routine(int exception_number)
+{
+ if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM))
+ return NULL;
+
+ /* Double fault not supported */
+ if (exception_number == SOS_EXCEPT_DOUBLE_FAULT)
+ return NULL;
+
+ /* Expected to be atomic */
+ return sos_exception_handler_array[exception_number];
+}
diff --git a/sos-code-article3/hwcore/exception.h b/sos-code-article3/hwcore/exception.h
new file mode 100644
index 0000000..7e52fe5
--- /dev/null
+++ b/sos-code-article3/hwcore/exception.h
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWEXCEPT_H_
+#define _SOS_HWEXCEPT_H_
+
+/**
+ * @file exception.c
+ *
+ * Hardware exception routines management.
+ */
+
+#ifndef ASM_SOURCE
+# include <sos/errno.h>
+#endif
+
+/**
+ * Standard Intel x86 exceptions.
+ *
+ * @see Intel x86 doc vol 3, section 5.12.
+ */
+#define SOS_EXCEPT_DIVIDE_ERROR 0 // No error code
+#define SOS_EXCEPT_DEBUG 1 // No error code
+#define SOS_EXCEPT_NMI_INTERRUPT 2 // No error code
+#define SOS_EXCEPT_BREAKPOINT 3 // No error code
+#define SOS_EXCEPT_OVERFLOW 4 // No error code
+#define SOS_EXCEPT_BOUND_RANGE_EXCEDEED 5 // No error code
+#define SOS_EXCEPT_INVALID_OPCODE 6 // No error code
+#define SOS_EXCEPT_DEVICE_NOT_AVAILABLE 7 // No error code
+#define SOS_EXCEPT_DOUBLE_FAULT 8 // Yes (Zero)
+#define SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN 9 // No error code
+#define SOS_EXCEPT_INVALID_TSS 10 // Yes
+#define SOS_EXCEPT_SEGMENT_NOT_PRESENT 11 // Yes
+#define SOS_EXCEPT_STACK_SEGMENT_FAULT 12 // Yes
+#define SOS_EXCEPT_GENERAL_PROTECTION 13 // Yes
+#define SOS_EXCEPT_PAGE_FAULT 14 // Yes
+#define SOS_EXCEPT_INTEL_RESERVED_1 15 // No
+#define SOS_EXCEPT_FLOATING_POINT_ERROR 16 // No
+#define SOS_EXCEPT_ALIGNEMENT_CHECK 17 // Yes (Zero)
+#define SOS_EXCEPT_MACHINE_CHECK 18 // No
+#define SOS_EXCEPT_INTEL_RESERVED_2 19 // No
+#define SOS_EXCEPT_INTEL_RESERVED_3 20 // No
+#define SOS_EXCEPT_INTEL_RESERVED_4 21 // No
+#define SOS_EXCEPT_INTEL_RESERVED_5 22 // No
+#define SOS_EXCEPT_INTEL_RESERVED_6 23 // No
+#define SOS_EXCEPT_INTEL_RESERVED_7 24 // No
+#define SOS_EXCEPT_INTEL_RESERVED_8 25 // No
+#define SOS_EXCEPT_INTEL_RESERVED_9 26 // No
+#define SOS_EXCEPT_INTEL_RESERVED_10 27 // No
+#define SOS_EXCEPT_INTEL_RESERVED_11 28 // No
+#define SOS_EXCEPT_INTEL_RESERVED_12 29 // No
+#define SOS_EXCEPT_INTEL_RESERVED_13 30 // No
+#define SOS_EXCEPT_INTEL_RESERVED_14 31 // No
+
+#ifndef ASM_SOURCE
+
+typedef void (*sos_exception_handler_t)(int exception_number);
+
+sos_ret_t sos_exceptions_setup(void);
+sos_ret_t sos_exception_set_routine(int exception_number,
+ sos_exception_handler_t routine);
+sos_exception_handler_t sos_exception_get_routine(int exception_number);
+#endif /* ! ASM_SOURCE */
+
+#endif /* _SOS_HWEXCEPT_H_ */
diff --git a/sos-code-article3/hwcore/exception_wrappers.S b/sos-code-article3/hwcore/exception_wrappers.S
new file mode 100644
index 0000000..2f7665c
--- /dev/null
+++ b/sos-code-article3/hwcore/exception_wrappers.S
@@ -0,0 +1,197 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "exception.h"
+
+.file "exception_wrappers.S"
+
+.text
+
+/* The address of the table of handlers (defined in exception.c) */
+.extern sos_exception_handler_array
+
+/* The address of the table of wrappers (defined below, and shared
+ with exception.c */
+.globl sos_exception_wrapper_array
+
+
+/**
+ * For exceptions with/without error code, refer to Intel x86 doc vol 3,
+ * section 5.12
+ */
+
+/* These wrappers are for exceptions without error code */
+.irp id, \
+ SOS_EXCEPT_DIVIDE_ERROR, \
+ SOS_EXCEPT_DEBUG, \
+ SOS_EXCEPT_NMI_INTERRUPT, \
+ SOS_EXCEPT_BREAKPOINT, \
+ SOS_EXCEPT_OVERFLOW, \
+ SOS_EXCEPT_BOUND_RANGE_EXCEDEED, \
+ SOS_EXCEPT_INVALID_OPCODE, \
+ SOS_EXCEPT_DEVICE_NOT_AVAILABLE, \
+ SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN, \
+ SOS_EXCEPT_INTEL_RESERVED_1, \
+ SOS_EXCEPT_FLOATING_POINT_ERROR, \
+ SOS_EXCEPT_MACHINE_CHECK, \
+ SOS_EXCEPT_INTEL_RESERVED_2, \
+ SOS_EXCEPT_INTEL_RESERVED_3, \
+ SOS_EXCEPT_INTEL_RESERVED_4, \
+ SOS_EXCEPT_INTEL_RESERVED_5, \
+ SOS_EXCEPT_INTEL_RESERVED_6, \
+ SOS_EXCEPT_INTEL_RESERVED_7, \
+ SOS_EXCEPT_INTEL_RESERVED_8, \
+ SOS_EXCEPT_INTEL_RESERVED_9, \
+ SOS_EXCEPT_INTEL_RESERVED_10, \
+ SOS_EXCEPT_INTEL_RESERVED_11, \
+ SOS_EXCEPT_INTEL_RESERVED_12, \
+ SOS_EXCEPT_INTEL_RESERVED_13, \
+ SOS_EXCEPT_INTEL_RESERVED_14
+
+ .p2align 2, 0x90
+ sos_exception_wrapper_\id:
+ .type sos_exception_wrapper_\id,@function
+
+ /* Fake error code */
+ pushl $0
+ /* Backup the context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Call the handler with exception number as
+ * argument */
+ pushl $\id
+ leal sos_exception_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+
+ popl %ebp
+ /* Remove fake error code */
+ addl $4, %esp
+ iret
+.endr
+
+ /* These wrappers are for exceptions with error code */
+.irp id, \
+ SOS_EXCEPT_INVALID_TSS, \
+ SOS_EXCEPT_SEGMENT_NOT_PRESENT, \
+ SOS_EXCEPT_STACK_SEGMENT_FAULT, \
+ SOS_EXCEPT_GENERAL_PROTECTION, \
+ SOS_EXCEPT_PAGE_FAULT, \
+ SOS_EXCEPT_ALIGNEMENT_CHECK
+
+ .p2align 2, 0x90
+ sos_exception_wrapper_\id:
+ .type sos_exception_wrapper_\id,@function
+
+ /* ret eflags */
+ /* ret cs */
+ /* ret eip */
+ /* Error code */
+
+ /* Backup the context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Call the handler with exception number as
+ * argument */
+ pushl $\id
+ leal sos_exception_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Error code isn't compatible with iretd */
+ addl $4, %esp
+
+ iret
+.endr
+
+
+/* Double fault handler not supported. We must define it since we
+ define an entry for it in the sos_exception_wrapper_array. */
+.irp id, SOS_EXCEPT_DOUBLE_FAULT
+.p2align 2, 0x90
+sos_exception_wrapper_\id:
+.type sos_exception_wrapper_\id,@function
+1: hlt
+ jmp 1b /* Machine halting */
+.endr
+
+/* Build the sos_irq_wrapper_array, shared with interrupt.c */
+.section ".rodata"
+.p2align 5, 0x0
+sos_exception_wrapper_array:
+ .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
+ 16,17,18,19,20,21,22,23,24,25,26,27,29,30,31
+ .long (sos_exception_wrapper_\id)
+ .endr
diff --git a/sos-code-article3/hwcore/gdt.c b/sos-code-article3/hwcore/gdt.c
new file mode 100644
index 0000000..7945c8c
--- /dev/null
+++ b/sos-code-article3/hwcore/gdt.c
@@ -0,0 +1,150 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "segment.h"
+
+#include "gdt.h"
+
+
+/**
+ * The sructure of a segment descriptor.
+ *
+ * @see Intel x86 doc, Vol 3, section 3.4.3, figure 3-8. For segment
+ * types, see section 3.5
+ */
+struct x86_segment_descriptor
+{
+ /* Lowest dword */
+ sos_ui16_t limit_15_0; /* Segment limit, bits 15..0 */
+ sos_ui16_t base_paged_addr_15_0; /* Base address, bits 15..0 */
+
+ /* Highest dword */
+ sos_ui8_t base_paged_addr_23_16; /* Base address bits 23..16 */
+ sos_ui8_t segment_type:4; /* Section 3.4.3.1 (code/data)
+ and 3.5 (system) of Intel x86 vol 3 */
+ sos_ui8_t descriptor_type:1; /* 0=system, 1=Code/Data */
+ sos_ui8_t dpl:2;
+ sos_ui8_t present:1;
+
+ sos_ui8_t limit_19_16:4; /* Segment limit, bits 19..16 */
+ sos_ui8_t custom:1;
+ sos_ui8_t zero:1;
+ sos_ui8_t op_size:1; /* 0=16bits instructions, 1=32bits */
+ sos_ui8_t granularity:1; /* 0=limit in bytes, 1=limit in pages */
+
+ sos_ui8_t base_paged_addr_31_24; /* Base address bits 31..24 */
+} __attribute__ ((packed, aligned (8)));
+
+
+/**
+ * The GDT register, which stores the address and size of the
+ * GDT.
+ *
+ * @see Intel x86 doc vol 3, section 2.4, figure 2-4; and section
+ * 3.5.1
+ */
+struct x86_gdt_register {
+ /* The maximum GDT offset allowed to access an entry in the GDT */
+ sos_ui16_t limit;
+
+ /* This is not exactly a "virtual" address, ie an adddress such as
+ those of instructions and data; this is a "linear" address, ie an
+ address in the paged memory. However, in SOS we configure the
+ segmented memory as a "flat" space: the 0-4GB segment-based (ie
+ "virtual") addresses directly map to the 0-4GB paged memory (ie
+ "linear"), so that the "linear" addresses are numerically equal
+ to the "virtual" addresses: this base_addr will thus be the same
+ as the address of the gdt array */
+ sos_ui32_t base_addr;
+} __attribute__((packed, aligned(8)));
+
+
+/**
+ * Helper macro that builds a Segment descriptor for the virtual
+ * 0..4GB addresses to be mapped to the linear 0..4GB linear
+ * addresses.
+ */
+#define BUILD_GDTE(descr_privilege_level,is_code) \
+ ((struct x86_segment_descriptor) { \
+ .limit_15_0= 0xffff, \
+ .base_paged_addr_15_0= 0, \
+ .base_paged_addr_23_16= 0, \
+ .segment_type= ((is_code)?0xb:0x3), \
+ /* With descriptor_type (below) = 1 (code/data), \
+ * see Figure 3-1 of section 3.4.3.1 in Intel \
+ * x86 vol 3: \
+ * - Code (bit 3 = 1): \
+ * bit 0: 1=Accessed \
+ * bit 1: 1=Readable \
+ * bit 2: 0=Non-Conforming \
+ * - Data (bit 3 = 0): \
+ * bit 0: 1=Accessed \
+ * bit 1: 1=Writable \
+ * bit 2: 0=Expand up (stack-related) \
+ * For Conforming/non conforming segments, see \
+ * Intel x86 Vol 3 section 4.8.1.1 \
+ */ \
+ .descriptor_type= 1, /* 1=Code/Data */ \
+ .dpl= ((descr_privilege_level) & 0x3), \
+ .present= 1, \
+ .limit_19_16= 0xf, \
+ .custom= 0, \
+ .op_size= 1, /* 32 bits instr/data */ \
+ .granularity= 1 /* limit is in 4kB Pages */ \
+ })
+
+
+/** The actual GDT */
+static struct x86_segment_descriptor gdt[] = {
+ [SOS_SEG_NULL] = (struct x86_segment_descriptor){ 0, },
+ [SOS_SEG_KCODE] = BUILD_GDTE(0, 1),
+ [SOS_SEG_KDATA] = BUILD_GDTE(0, 0),
+};
+
+sos_ret_t sos_gdt_setup(void)
+{
+ struct x86_gdt_register gdtr;
+
+ /* Address of the GDT */
+ gdtr.base_addr = (sos_ui32_t) gdt;
+
+ /* The limit is the maximum offset in bytes from the base address of
+ the GDT */
+ gdtr.limit = sizeof(gdt) - 1;
+
+ /* Commit the GDT into the CPU, and update the segment
+ registers. The CS register may only be updated with a long jump
+ to an absolute address in the given segment (see Intel x86 doc
+ vol 3, section 4.8.1). */
+ asm volatile ("lgdt %0 \n\
+ ljmp %1,$1f \n\
+ 1: \n\
+ movw %2, %%ax \n\
+ movw %%ax, %%ss \n\
+ movw %%ax, %%ds \n\
+ movw %%ax, %%es \n\
+ movw %%ax, %%fs \n\
+ movw %%ax, %%gs"
+ :
+ :"m"(gdtr),
+ "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE)),
+ "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA))
+ :"memory","eax");
+
+ return SOS_OK;
+}
diff --git a/sos-code-article3/hwcore/gdt.h b/sos-code-article3/hwcore/gdt.h
new file mode 100644
index 0000000..b7e3f4c
--- /dev/null
+++ b/sos-code-article3/hwcore/gdt.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_GDT_H_
+#define _SOS_GDT_H_
+
+/**
+ * @file gdt.h
+ *
+ * The routines that manage the GDT, the table that maps the virtual
+ * addresses (data/instructions, segment-relative), to "linear"
+ * addresses (ie paged-memory). In SOS/x86, we use a "flat" virtual
+ * space, ie the virtual and linear spaces are equivalent.
+ *
+ * @see Intel x86 doc vol 3, chapter 3
+ */
+
+#include <sos/errno.h>
+
+/**
+ * Configure the virtual space as a direct mapping to the linear
+ * address space (ie "flat" virtual space).
+ */
+sos_ret_t sos_gdt_setup(void);
+
+#endif /* _SOS_GDT_H_ */
diff --git a/sos-code-article3/hwcore/i8254.c b/sos-code-article3/hwcore/i8254.c
new file mode 100644
index 0000000..5fbb156
--- /dev/null
+++ b/sos-code-article3/hwcore/i8254.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <hwcore/ioports.h>
+
+#include "i8254.h"
+
+/** 82c54 clock frequency */
+#define I8254_MAX_FREQ 1193180
+
+/* Ports to communicate with the 82c54 */
+#define I8254_TIMER0 0x40
+#define I8254_TIMER1 0x41
+#define I8254_TIMER2 0x42
+#define I8254_CONTROL 0x43
+
+/**
+ * Configure the first timer of the 82c54 chip as a rate generator,
+ * which will raise an IRQ0 on a regular periodic basis, as given by
+ * the freq parameter. Second (RAM refresh) and third (speaker) timers
+ * are left unchanged. Maximum frequency is that of the 8254 clock, ie
+ * 1193180 Hz.
+ *
+ * Ahhh PC systems are nice toys: this maximum "strange" frequency
+ * equals that of the NTSC clock (14.31818 MHz) divided by 12. In
+ * turn, the famous 4.77 MHz cpu clock frequency of the first IBM PC
+ * is this same NTSC frequency divided by 3. Why the NTSC frequency as
+ * a base "standard" ? Because the 14.31818 MHz quartz were cheap at
+ * that time, and because it allows to simply drive altogether the
+ * cpu, the "time of day" timer, and the video signal generators.
+ */
+sos_ret_t sos_i8254_set_frequency(unsigned int freq)
+{
+ unsigned int nb_tick;
+
+ if (freq <= 0)
+ return -SOS_EINVAL;
+
+ /* Compute counter value */
+ nb_tick = I8254_MAX_FREQ / freq;
+
+ /* Counter must be between 1 and 65536 */
+ if (nb_tick > 65536)
+ return -SOS_EINVAL;
+ if (nb_tick <= 0)
+ return -SOS_EINVAL;
+
+ /* The i8254 interprets 0 to mean counter == 65536, because 65536
+ cannot be coded on 16bits */
+ if (nb_tick == 65536)
+ nb_tick = 0;
+
+ /* We want to configure timer0, we want to send both LSB+MSB to set
+ timer0 freq (-> 0x30), and we configure timer0 in mode 2, ie as a
+ rate generator (-> 0x4) ==> 0x34 */
+ outb(0x34, I8254_CONTROL);
+
+ /* Send LSB of counter first */
+ outb((nb_tick & 0xFF), I8254_TIMER0);
+
+ /* Send MSB of counter */
+ outb((nb_tick >> 8) & 0xFF, I8254_TIMER0);
+
+ return SOS_OK;
+}
diff --git a/sos-code-article3/hwcore/i8254.h b/sos-code-article3/hwcore/i8254.h
new file mode 100644
index 0000000..4838ff4
--- /dev/null
+++ b/sos-code-article3/hwcore/i8254.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_i8259_H_
+#define _SOS_i8259_H_
+
+#include <sos/errno.h>
+
+/**
+ * @file i8254.h PC programmable timer
+ *
+ * Programmable timer routines. See the Intel 82C54 datasheet (on kos
+ * website).
+ *
+ * @see i82C54 datasheet on Kos website.
+ */
+
+/** Change timer interrupt (IRQ 0) frequency */
+sos_ret_t sos_i8254_set_frequency(unsigned int freq);
+
+#endif /* _SOS_i8259_H_ */
diff --git a/sos-code-article3/hwcore/i8259.c b/sos-code-article3/hwcore/i8259.c
new file mode 100644
index 0000000..8391c07
--- /dev/null
+++ b/sos-code-article3/hwcore/i8259.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "ioports.h"
+
+#include "i8259.h"
+
+#define PIC_MASTER 0x20
+#define PIC_SLAVE 0xa0
+
+/** Setup the 8259 PIC */
+sos_ret_t sos_i8259_setup(void)
+{
+ /* Send ICW1: 8086 mode + NOT Single ctrl + call address
+ interval=8 */
+ outb(0x11, PIC_MASTER);
+ outb(0x11, PIC_SLAVE);
+
+ /* Send ICW2: ctrl base address */
+ outb(0x20, PIC_MASTER+1);
+ outb(0x28, PIC_SLAVE+1);
+
+ /* Send ICW3 master: mask where slaves are connected */
+ outb(0x4, PIC_MASTER+1);
+ /* Send ICW3 slave: index where the slave is connected on master */
+ outb(0x2, PIC_SLAVE+1);
+
+ /* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */
+ outb(0x1, PIC_MASTER+1);
+ outb(0x1, PIC_SLAVE+1);
+
+ /* Send OCW1:
+ * Closing all IRQs : waiting for a correct handler The only IRQ
+ * enabled is the cascade (that's why we use 0xFB for the master) */
+ outb(0xFB, PIC_MASTER+1);
+ outb(0xFF, PIC_SLAVE+1);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_i8259_enable_irq_line(int numirq)
+{
+ if(numirq < 8)
+ /* irq on master PIC */
+ outb((inb(PIC_MASTER+1) & ~(1 << numirq)), PIC_MASTER+1);
+ else
+ /* irq on slave PIC */
+ outb((inb(PIC_SLAVE+1) & ~(1 << (numirq-8))), PIC_SLAVE+1);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_i8259_disable_irq_line(int numirq)
+{
+ if(numirq < 8)
+ /* irq on master PIC */
+ outb((inb(PIC_MASTER+1) | (1 << numirq)), PIC_MASTER+1);
+ else
+ /* irq on slave PIC */
+ outb((inb(PIC_SLAVE+1) | (1 << (numirq-8))), PIC_SLAVE+1);
+
+ return SOS_OK;
+}
diff --git a/sos-code-article3/hwcore/i8259.h b/sos-code-article3/hwcore/i8259.h
new file mode 100644
index 0000000..c1771dd
--- /dev/null
+++ b/sos-code-article3/hwcore/i8259.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_i8259_H_
+#define _SOS_i8259_H_
+
+#include <sos/errno.h>
+
+/**
+ * @file i8259.h PIC
+ *
+ * PIC Management routines. See the Intel 8259A datasheet (on kos
+ * website), page 9+. Should be not be used directly: only interrupt.c
+ * should use this.
+ *
+ * @see i8259A datasheet on Kos website.
+ */
+
+/** Setup PIC and Disable all IRQ lines */
+sos_ret_t sos_i8259_setup(void);
+
+sos_ret_t sos_i8259_enable_irq_line(int numirq);
+
+sos_ret_t sos_i8259_disable_irq_line(int numirq);
+
+#endif /* _SOS_i8259_H_ */
diff --git a/sos-code-article3/hwcore/idt.c b/sos-code-article3/hwcore/idt.c
new file mode 100644
index 0000000..51e3a9d
--- /dev/null
+++ b/sos-code-article3/hwcore/idt.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "segment.h"
+
+#include "idt.h"
+
+/**
+ * An entry in the IDT, or "IDTE" in the following, ie a reference to
+ * a interrupt/trap routine or a task gate to handle the sw/hw
+ * interrupts and exceptions.
+ *
+ * @see figure 5-2, intel x86 doc, vol 3
+ */
+struct x86_idt_entry
+{
+ /* Low dword */
+ sos_ui16_t offset_low; /* 15..0, offset of the routine in the segment */
+ sos_ui16_t seg_sel; /* 31..16, the ID of the segment */
+
+ /* High dword */
+ sos_ui8_t reserved:5; /* 4..0 */
+ sos_ui8_t flags:3; /* 7..5 */
+ sos_ui8_t type:3; /* 10..8 (interrupt gate, trap gate...) */
+ sos_ui8_t op_size:1; /* 11 (0=16bits instructions, 1=32bits instr.) */
+ sos_ui8_t zero:1; /* 12 */
+ sos_ui8_t dpl:2; /* 14..13 */
+ sos_ui8_t present:1; /* 15 */
+ sos_ui16_t offset_high; /* 31..16 */
+} __attribute__((packed));
+
+
+/**
+ * The IDT register, which stores the address and size of the
+ * IDT.
+ *
+ * @see Intel x86 doc vol 3, section 2.4, figure 2-4
+ */
+struct x86_idt_register
+{
+ /* The maximum GDT offset allowed to access an entry in the GDT */
+ sos_ui16_t limit;
+
+ /* This is not exactly a "virtual" address, ie an adddress such as
+ those of instructions and data; this is a "linear" address, ie an
+ address in the paged memory. However, in SOS we configure the
+ segmented memory as a "flat" space: the 0-4GB segment-based (ie
+ "virtual") addresses directly map to the 0-4GB paged memory (ie
+ "linear"), so that the "linear" addresses are numerically equal
+ to the "virtual" addresses: this base_addr will thus be the same
+ as the address of the gdt array */
+ sos_ui32_t base_addr;
+} __attribute__((packed, aligned (8)));
+
+
+static struct x86_idt_entry idt[SOS_IDTE_NUM];
+
+sos_ret_t sos_idt_setup()
+{
+ struct x86_idt_register idtr;
+ int i;
+
+ for (i = 0 ;
+ i < SOS_IDTE_NUM ;
+ i++)
+ {
+ struct x86_idt_entry *idte = idt + i;
+
+ /* Setup an empty IDTE interrupt gate, see figure 5-2 in Intel
+ x86 doc, vol 3 */
+ idte->seg_sel = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE);
+ idte->reserved = 0;
+ idte->flags = 0;
+ idte->type = 0x6; /* Interrupt gate (110b) */
+ idte->op_size = 1; /* 32bits instructions */
+ idte->zero = 0;
+
+ /* Disable this IDT entry for the moment */
+ sos_idt_set_handler(i, (sos_vaddr_t)NULL, 0/* Don't care */);
+ }
+
+ /*
+ * Setup the IDT register, see Intel x86 doc vol 3, section 5.8.
+ */
+
+ /* Address of the IDT */
+ idtr.base_addr = (sos_ui32_t) idt;
+
+ /* The limit is the maximum offset in bytes from the base address of
+ the IDT */
+ idtr.limit = sizeof(idt) - 1;
+
+ /* Commit the IDT into the CPU */
+ asm volatile ("lidt %0\n"::"m"(idtr):"memory");
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_idt_set_handler(int index,
+ sos_vaddr_t handler_address,
+ int lowest_priviledge /* 0..3 */)
+{
+ struct x86_idt_entry *idte;
+
+ if ((index < 0) || (index >= SOS_IDTE_NUM))
+ return -SOS_EINVAL;
+ if ((lowest_priviledge < 0) || (lowest_priviledge > 3))
+ return -SOS_EINVAL;
+
+ idte = idt + index;
+ if (handler_address != (sos_vaddr_t)NULL)
+ {
+ idte->offset_low = handler_address & 0xffff;
+ idte->offset_high = (handler_address >> 16) & 0xffff;
+ idte->dpl = lowest_priviledge;
+ idte->present = 1; /* Yes, there is a handler */
+ }
+ else /* Disable this IDT entry */
+ {
+ idte->offset_low = 0;
+ idte->offset_high = 0;
+ idte->dpl = 0;
+ idte->present = 0; /* No, there is no handler */
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_idt_get_handler(int index,
+ sos_vaddr_t *handler_address,
+ int *lowest_priviledge)
+{
+ if ((index < 0) || (index >= SOS_IDTE_NUM))
+ return -SOS_EINVAL;
+
+ if (handler_address != NULL)
+ *handler_address = idt[index].offset_low
+ | (idt[index].offset_high << 16);
+ if (lowest_priviledge != NULL)
+ *lowest_priviledge = idt[index].dpl;
+
+ return SOS_OK;
+}
diff --git a/sos-code-article3/hwcore/idt.h b/sos-code-article3/hwcore/idt.h
new file mode 100644
index 0000000..7afe364
--- /dev/null
+++ b/sos-code-article3/hwcore/idt.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_IDT_H_
+#define _SOS_IDT_H_
+
+/**
+ * @file idt.h
+ *
+ * Manage the x86 Interrupt Descriptor Table, the table which maps the
+ * hardware interrupt lines, hardware exceptions, and software
+ * interrupts, to software routines. We only define "interrupt gate"
+ * IDT entries. Don't use it directly; refer instead to interrupt.c,
+ * exceptions.c and syscall.c.
+ *
+ * @see Intel x86 doc, Vol 3, chapter 5
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+
+/* Mapping of the CPU exceptions in the IDT (imposed by Intel
+ standards) */
+#define SOS_EXCEPT_BASE 0
+#define SOS_EXCEPT_NUM 32
+#define SOS_EXCEPT_MAX (SOS_HWEXCEPT_BASE + SOS_HWEXCEPT_NUM - 1)
+
+/* Mapping of the IRQ lines in the IDT */
+#define SOS_IRQ_BASE 32
+#define SOS_IRQ_NUM 16
+#define SOS_IRQ_MAX (SOS_IRQ_BASE + SOS_IRQ_NUM - 1)
+
+/**
+ * Number of IDT entries.
+ *
+ * @note Must be large enough to map the hw interrupts, the exceptions
+ * (=> total is 48 entries), and the syscall(s). Since our syscall
+ * will be 0x42, it must be >= 0x43. Intel doc limits this to 256
+ * entries, we use this limit.
+ */
+#define SOS_IDTE_NUM 256 /* 0x100 */
+
+/** Initialization routine: all the IDT entries (or "IDTE") are marked
+ "not present". */
+sos_ret_t sos_idt_setup(void);
+
+/**
+ * Enable the IDT entry if handler_address != NULL, with the given
+ * lowest_priviledge.\ Disable the IDT entry when handler_address ==
+ * NULL (the lowest_priviledge parameter is then ignored). Intel doc
+ * says that there must not be more than 256 entries.
+ *
+ * @note IRQ Unsafe
+ */
+sos_ret_t sos_idt_set_handler(int index,
+ sos_vaddr_t handler_address,
+ int lowest_priviledge /* 0..3 */);
+
+
+/**
+ * @note IRQ Unsafe
+ *
+ * @return the handler address and DPL in the 2nd and 3rd
+ * parameters
+ */
+sos_ret_t sos_idt_get_handler(int index,
+ sos_vaddr_t *handler_address,
+ int *lowest_priviledge);
+
+#endif /* _SOS_IDT_H_ */
diff --git a/sos-code-article3/hwcore/ioports.h b/sos-code-article3/hwcore/ioports.h
new file mode 100644
index 0000000..443acb7
--- /dev/null
+++ b/sos-code-article3/hwcore/ioports.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2004 All GPL'ed OS
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_IOPORTS_H_
+#define _SOS_IOPORTS_H_
+
+/**
+ * @ioports.h
+ *
+ * Intel-specific I/O space access routines.
+ */
+
+/* This macro allows to write to an I/O port */
+#define outb(value, port) \
+ __asm__ volatile ( \
+ "outb %b0,%w1" \
+ ::"a" (value),"Nd" (port) \
+ ) \
+
+// read one byte from port
+#define inb(port) \
+({ \
+ unsigned char _v; \
+ __asm__ volatile ( \
+ "inb %w1,%0" \
+ :"=a" (_v) \
+ :"Nd" (port) \
+ ); \
+ _v; \
+})
+
+#endif /* _SOS_IOPORTS_H_ */
diff --git a/sos-code-article3/hwcore/irq.c b/sos-code-article3/hwcore/irq.c
new file mode 100644
index 0000000..6ec3371
--- /dev/null
+++ b/sos-code-article3/hwcore/irq.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "idt.h"
+#include "i8259.h"
+
+#include "irq.h"
+
+/* array of IRQ wrappers, defined in irq_wrappers.S */
+extern sos_vaddr_t sos_irq_wrapper_array[SOS_IRQ_NUM];
+
+/* arrays of IRQ handlers, shared with irq_wrappers.S */
+sos_irq_handler_t sos_irq_handler_array[SOS_IRQ_NUM] = { NULL, };
+
+
+sos_ret_t sos_irq_setup(void)
+{
+ return sos_i8259_setup();
+}
+
+
+sos_ret_t sos_irq_set_routine(int irq_level,
+ sos_irq_handler_t routine)
+{
+ sos_ret_t retval;
+ sos_ui32_t flags;
+
+ if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM))
+ return -SOS_EINVAL;
+
+ sos_disable_IRQs(flags);
+
+ retval = SOS_OK;
+
+ /* Set the irq routine to be called by the IRQ wrapper */
+ sos_irq_handler_array[irq_level] = routine;
+
+ /* If the irq is to be enabled, update the IDT with the IRQ
+ wrapper */
+ if (routine != NULL)
+ {
+ retval
+ = sos_idt_set_handler(SOS_IRQ_BASE + irq_level,
+ (sos_vaddr_t) sos_irq_wrapper_array[irq_level],
+ 0 /* CPL0 routine */);
+ /* A problem occured */
+ if (retval != SOS_OK)
+ sos_irq_handler_array[irq_level] = NULL;
+ }
+ else /* Disable this idt entry */
+ {
+ retval
+ = sos_idt_set_handler(SOS_IRQ_BASE + irq_level,
+ (sos_vaddr_t)NULL /* Disable IDTE */,
+ 0 /* Don't care */);
+ }
+
+ /* Update the PIC only if an IRQ handler has been set */
+ if (sos_irq_handler_array[irq_level] != NULL)
+ sos_i8259_enable_irq_line(irq_level);
+ else
+ sos_i8259_disable_irq_line(irq_level);
+
+ sos_restore_IRQs(flags);
+ return retval;
+}
+
+
+sos_irq_handler_t sos_irq_get_routine(int irq_level)
+{
+ if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM))
+ return NULL;
+
+ /* Expected to be atomic */
+ return sos_irq_handler_array[irq_level];
+}
diff --git a/sos-code-article3/hwcore/irq.h b/sos-code-article3/hwcore/irq.h
new file mode 100644
index 0000000..5b39230
--- /dev/null
+++ b/sos-code-article3/hwcore/irq.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWINTR_H_
+#define _SOS_HWINTR_H_
+
+/**
+ * @file irq.c
+ *
+ * Hardware interrupts routines management.
+ */
+
+#include <sos/errno.h>
+
+#define sos_save_flags(flags) \
+ asm volatile("pushfl ; popl %0":"=g"(flags)::"memory")
+#define sos_restore_flags(flags) \
+ asm volatile("push %0; popfl"::"g"(flags):"memory")
+
+#define sos_disable_IRQs(flags) \
+ ({ sos_save_flags(flags); asm("cli\n"); })
+#define sos_restore_IRQs(flags) \
+ sos_restore_flags(flags)
+
+/* Usual IRQ levels */
+#define SOS_IRQ_TIMER 0
+#define SOS_IRQ_KEYBOARD 1
+#define SOS_IRQ_SLAVE_PIC 2
+#define SOS_IRQ_COM2 3
+#define SOS_IRQ_COM1 4
+#define SOS_IRQ_LPT2 5
+#define SOS_IRQ_FLOPPY 6
+#define SOS_IRQ_LPT1 7
+#define SOS_IRQ_8_NOT_DEFINED 8
+#define SOS_IRQ_RESERVED_1 9
+#define SOS_IRQ_RESERVED_2 10
+#define SOS_IRQ_RESERVED_3 11
+#define SOS_IRQ_RESERVED_4 12
+#define SOS_IRQ_COPROCESSOR 13
+#define SOS_IRQ_HARDDISK 14
+#define SOS_IRQ_RESERVED_5 15
+
+typedef void (*sos_irq_handler_t)(int irq_level);
+
+/** Setup the PIC */
+sos_ret_t sos_irq_setup(void);
+
+/**
+ * If the routine is not NULL, the IDT is setup to call an IRQ
+ * wrapper upon interrupt, which in turn will call the routine, and
+ * the PIC is programmed to raise an irq.\ If the routine is
+ * NULL, we disable the irq line.
+ */
+sos_ret_t sos_irq_set_routine(int irq_level,
+ sos_irq_handler_t routine);
+
+sos_irq_handler_t sos_irq_get_routine(int irq_level);
+
+#endif /* _SOS_HWINTR_H_ */
diff --git a/sos-code-article3/hwcore/irq_wrappers.S b/sos-code-article3/hwcore/irq_wrappers.S
new file mode 100644
index 0000000..cf3355d
--- /dev/null
+++ b/sos-code-article3/hwcore/irq_wrappers.S
@@ -0,0 +1,173 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#define ASM_SOURCE 1
+
+.file "irq_wrappers.S"
+
+.text
+
+/* The address of the table of handlers (defined in irq.c) */
+.extern sos_irq_handler_array
+
+/* The address of the table of wrappers (defined below, and shared
+ with irq.c */
+.globl sos_irq_wrapper_array
+
+
+/* These pre-handlers are for IRQ (Master PIC) */
+.irp id, 0,1,2,3,4,5,6,7
+
+ .p2align 2, 0x90
+
+ sos_irq_wrapper_\id:
+ .type sos_irq_wrapper_\id,@function
+
+ /*
+ * Backup the CPU context
+ */
+
+ /* Fake error code */
+ pushl $0
+
+ /* Backup the actual context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Send EOI to PIC. See Intel 8259 datasheet
+ available on Kos website */
+ movb $0x20, %al
+ outb %al, $0x20
+
+ /*
+ * Call the handler with IRQ number as argument
+ */
+ pushl $\id
+ leal sos_irq_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Remove fake error code */
+ addl $4, %esp
+
+ iret
+ .endr
+
+
+/* These pre-handlers are for IRQ (Slave PIC) */
+.irp id, 8,9,10,11,12,13,14,15
+
+ .p2align 2, 0x90
+
+ sos_irq_wrapper_\id:
+ .type sos_irq_wrapper_\id,@function
+
+ /*
+ * Backup the CPU context
+ */
+
+ /* Fake error code */
+ pushl $0
+
+ /* Backup the actual context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Send EOI to PIC. See Intel 8259 datasheet
+ available on Kos website */
+ movb $0x20, %al
+ outb %al, $0xa0
+ outb %al, $0x20
+
+ /*
+ * Call the handler with IRQ number as argument
+ */
+ pushl $\id
+ leal sos_irq_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Remove fake error code */
+ addl $4, %esp
+
+ iret
+ .endr
+
+/* Build the sos_irq_wrapper_array, shared with irq.c */
+.section ".rodata"
+.p2align 5, 0x0
+sos_irq_wrapper_array:
+ .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .long (sos_irq_wrapper_\id)
+ .endr
diff --git a/sos-code-article3/hwcore/segment.h b/sos-code-article3/hwcore/segment.h
new file mode 100644
index 0000000..37bdf5e
--- /dev/null
+++ b/sos-code-article3/hwcore/segment.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWSEGS_H_
+#define _SOS_HWSEGS_H_
+
+/**
+ * @file segments.h
+ *
+ * Global and local (GDT/LDT) segment descriptor definition and
+ * structure. These segments map virtual addresses (ie
+ * data/instruction addresses, relative to these segment descriptors)
+ * to linear addresses (ie addresses in the paged-memory space).
+ *
+ * @see Intel x86 doc, vol 3 chapter 3.
+ */
+
+#include <sos/types.h>
+
+/*
+ * Global segment selectors (GDT) for SOS/x86.
+ *
+ * @see gdt.h
+ */
+#define SOS_SEG_NULL 0 /* NULL segment, unused by the procesor */
+#define SOS_SEG_KCODE 1 /* Kernel code segment */
+#define SOS_SEG_KDATA 2 /* Kernel data segment */
+
+
+/**
+ * Helper macro that builds a segment register's value
+ */
+#define SOS_BUILD_SEGMENT_REG_VALUE(desc_privilege,in_ldt,seg_index) \
+ ( (((desc_privilege) & 0x3) << 0) \
+ | (((in_ldt)?1:0) << 2) \
+ | ((seg_index) << 3) )
+
+
+/*
+ * Local segment selectors (LDT) for SOS/x86
+ */
+/* None */
+
+#endif /* _SOS_HWSEGS_H_ */
diff --git a/sos-code-article3/sos/assert.h b/sos-code-article3/sos/assert.h
new file mode 100644
index 0000000..a14ca0b
--- /dev/null
+++ b/sos-code-article3/sos/assert.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2004 The KOS Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ASSERT_H_
+#define _SOS_ASSERT_H_
+
+#include <drivers/bochs.h>
+#include <drivers/x86_videomem.h>
+
+/**
+ * If the expr is FALSE, print a message and halt the machine
+ */
+#define SOS_ASSERT_FATAL(expr) \
+ ({ \
+ int __res=(int)(expr); \
+ if (! __res) { \
+ asm("cli\n"); /* disable interrupts -- x86 only */ \
+ sos_bochs_printf("%s@%s:%d Assertion " # expr " failed\n", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ sos_x86_videomem_printf(24, 0, 12, \
+ "%s@%s:%d Assertion " # expr " failed", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ for (;;) asm("hlt;") ; /* Infinite loop, ie simple system halt */ \
+ } \
+ })
+
+
+#endif /* _SOS_ASSERT_H_ */
diff --git a/sos-code-article3/sos/errno.h b/sos-code-article3/sos/errno.h
new file mode 100644
index 0000000..2c7bada
--- /dev/null
+++ b/sos-code-article3/sos/errno.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ERRNO_H_
+#define _SOS_ERRNO_H_
+
+/**
+ * @file errno.h
+ *
+ * SOS return value codes and errors.
+ */
+
+/* Positive values of the error codes */
+#define SOS_OK 0 /* No error */
+#define SOS_EINVAL 1 /* Invalid argument */
+#define SOS_ENOSUP 2 /* Operation not supported */
+#define SOS_ENOMEM 3 /* No available memory */
+#define SOS_EFATAL 255 /* Internal fatal error */
+
+/* A negative value means that an error occured. For
+ * example -SOS_EINVAL means that the error was "invalid
+ * argument" */
+typedef int sos_ret_t;
+
+#endif /* _SOS_ERRNO_H_ */
diff --git a/sos-code-article3/sos/klibc.c b/sos-code-article3/sos/klibc.c
new file mode 100644
index 0000000..277a15c
--- /dev/null
+++ b/sos-code-article3/sos/klibc.c
@@ -0,0 +1,271 @@
+/* Copyright (C) 2004 David Decotigny (with INSA Rennes for vsnprintf)
+ Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "klibc.h"
+
+/* For an optimized version, see BSD sources ;) */
+void *memcpy(void *dst0, const void *src0, register unsigned int size)
+{
+ char *dst;
+ const char *src;
+ for (dst = (char*)dst0, src = (const char*)src0 ;
+ size > 0 ;
+ dst++, src++, size--)
+ *dst = *src;
+ return dst0;
+}
+
+/* ditto */
+void *memset(void *dst0, register int c, register unsigned int length)
+{
+ char *dst;
+ for (dst = (char*) dst0 ;
+ length > 0 ;
+ dst++, length --)
+ *dst = (char)c;
+ return dst0;
+}
+
+int memcmp(const void *s1, const void *s2, sos_size_t len)
+{
+ const unsigned char *c1, *c2;
+ unsigned int i;
+
+ for (i = 0, c1 = s1, c2 = s2; i < len; i++, c1++, c2++)
+ {
+ if(*c1 != *c2)
+ return *c1 - *c2;
+ }
+
+ return 0;
+}
+
+
+unsigned int strlen(register const char *str)
+{
+ unsigned int retval = 0;
+
+ while (*str++)
+ retval++;
+
+ return retval;
+}
+
+
+unsigned int strnlen(const char * s, sos_size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */continue;
+
+ return sc - s;
+}
+
+
+char *strzcpy(register char *dst, register const char *src, register int len)
+{
+ int i;
+
+ if (len <= 0)
+ return dst;
+
+ for (i = 0; i < len; i++)
+ {
+ dst[i] = src[i];
+ if(src[i] == '\0')
+ return dst;
+ }
+
+ dst[len-1] = '\0';
+ return dst;
+}
+
+
+char *strzcat (char *dest, const char *src, sos_size_t n)
+{
+ char *res = dest;
+
+ for ( ; *dest ; dest++);
+
+ for ( ; *src ; src++, dest++) {
+ *dest = *src;
+ n--;
+ if (n <= 0)
+ break;
+ }
+
+ *dest = '\0';
+ return res;
+}
+
+int strcmp(register const char *s1, register const char *s2)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == 0)
+ return (0);
+
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
+
+
+int strncmp(register const char *s1, register const char *s2, register int len)
+{
+ char c1 = '\0', c2 = '\0';
+
+ while (len > 0)
+ {
+ c1 = (unsigned char) *s1++;
+ c2 = (unsigned char) *s2++;
+ if (c1 == '\0' || c1 != c2)
+ return c1 - c2;
+ len--;
+ }
+
+ return c1 - c2;
+}
+
+
+/* I (d2) borrowed and rewrote this for Nachos/INSA Rennes. Thanks to
+ them for having kindly allowed me to do so. */
+int vsnprintf(char *buff, sos_size_t len, const char * format, va_list ap)
+{
+ sos_size_t i, result;
+
+ if (!buff || !format || (len < 0))
+ return -1;
+
+#define PUTCHAR(thechar) \
+ do { \
+ if (result < len-1) \
+ *buff++ = (thechar); \
+ result++; \
+ } while (0)
+
+ result = 0;
+ for(i=0 ; format[i] != '\0' ; i++){
+ switch (format[i])
+ {
+ case '%':
+ i++;
+ switch(format[i])
+ {
+ case '%':
+ {
+ PUTCHAR('%');
+ break;
+ }
+ case 'i':;
+ case 'd':
+ {
+ int integer = va_arg(ap,int);
+ int cpt2 = 0;
+ char buff_int[16];
+
+ if (integer<0)
+ PUTCHAR('-');
+ /* Ne fait pas integer = -integer ici parce que INT_MIN
+ n'a pas d'equivalent positif (int = [-2^31, 2^31-1]) */
+
+ do {
+ int m10 = integer%10;
+ m10 = (m10 < 0)? -m10:m10;
+ buff_int[cpt2++]=(char)('0'+ m10);
+ integer=integer/10;
+ } while(integer!=0);
+
+ for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
+ PUTCHAR(buff_int[cpt2]);
+
+ break;
+ }
+
+ case 'c':
+ {
+ int value = va_arg(ap,int);
+ PUTCHAR((char)value);
+ break;
+ }
+
+ case 's':
+ {
+ char *string = va_arg(ap,char *);
+ if (! string)
+ string = "(null)";
+ for( ; *string != '\0' ; string++)
+ PUTCHAR(*string);
+ break;
+ }
+
+ case 'x':
+ {
+ unsigned int hexa = va_arg(ap,int);
+ unsigned int nb;
+ int i, had_nonzero = 0;
+ for(i=0 ; i < 8 ; i++)
+ {
+ nb = (unsigned int)(hexa << (i*4));
+ nb = (nb >> 28) & 0xf;
+ // Skip the leading zeros
+ if (nb == 0)
+ {
+ if (had_nonzero)
+ PUTCHAR('0');
+ }
+ else
+ {
+ had_nonzero = 1;
+ if (nb < 10)
+ PUTCHAR('0'+nb);
+ else
+ PUTCHAR('a'+(nb-10));
+ }
+ }
+ if (! had_nonzero)
+ PUTCHAR('0');
+ break;
+ }
+ break;
+
+ default:
+ PUTCHAR('%');
+ PUTCHAR(format[i]);
+ }
+ break;
+
+ default:
+ PUTCHAR(format[i]);
+ }
+ }
+
+ *buff = '\0';
+ return result;
+}
+
+
+int snprintf(char * buff, sos_size_t len, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ len = vsnprintf(buff, len, format, ap);
+ va_end(ap);
+
+ return len;
+}
diff --git a/sos-code-article3/sos/klibc.h b/sos-code-article3/sos/klibc.h
new file mode 100644
index 0000000..a8b9d49
--- /dev/null
+++ b/sos-code-article3/sos/klibc.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_KLIBC_H_
+#define _SOS_KLIBC_H_
+
+/**
+ * @file klibc.h
+ *
+ * Basic libc-style support for common useful functions (string.h,
+ * stdarg.h), some with slight non-standard behavior (see comments).
+ */
+
+#include <sos/types.h>
+
+/* string.h functions */
+
+void *memcpy(void *dst, const void *src, register unsigned int size ) ;
+void *memset(void *dst, register int c, register unsigned int length ) ;
+int memcmp(const void *s1, const void *s2, sos_size_t n);
+
+unsigned int strlen( register const char *str) ;
+unsigned int strnlen(const char * s, sos_size_t maxlen);
+
+/**
+ * @note Same as strncpy(), with a slightly different semantic.
+ * Actually, strncpy(3C) says " The result will not be null-terminated
+ * if the length of 'from' is n or more.". Here, 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcpy( register char *dst, register const char *src,
+ register int len ) ;
+
+/**
+ * @note Same as strncat(), with the same semantic : 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcat (char *dest, const char *src,
+ const sos_size_t len);
+
+int strcmp(register const char *s1, register const char *s2 );
+int strncmp(register const char *s1, register const char *s2,
+ register int len );
+
+/* Basic stdarg.h macros. Taken from gcc support files */
+#define __GNUC_VA_LIST
+typedef void *__gnuc_va_list;
+typedef __gnuc_va_list va_list;
+#define __va_rounded_size(TYPE) \
+ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+#define va_start(AP, LASTARG) \
+ (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG)))
+#define va_end(AP) \
+ ((void)0)
+#define va_arg(AP, TYPE) \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
+ *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
+#define __va_copy(dest, src) \
+ (dest) = (src)
+
+/* stdarg.h functions. There might be a non-standard behavior: there
+ will always be a trailing '\0' in the resulting string */
+int vsnprintf(char *, sos_size_t, const char *, va_list);
+int snprintf(char *, sos_size_t, const char *, /*args*/ ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+#endif /* _SOS_KLIBC_H_ */
diff --git a/sos-code-article3/sos/list.h b/sos-code-article3/sos/list.h
new file mode 100644
index 0000000..67e72f3
--- /dev/null
+++ b/sos-code-article3/sos/list.h
@@ -0,0 +1,186 @@
+/* Copyright (C) 2001 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_LIST_H_
+#define _SOS_LIST_H_
+
+/**
+ * @file list.h
+ *
+ * Circular doubly-linked lists implementation entirely based on C
+ * macros
+ */
+
+
+/* *_named are used when next and prev links are not exactly next
+ and prev. For instance when we have next_in_team, prev_in_team,
+ prev_global and next_global */
+
+#define list_init_named(list,prev,next) \
+ ((list) = NULL)
+
+#define list_singleton_named(list,item,prev,next) ({ \
+ (item)->next = (item)->prev = (item); \
+ (list) = (item); \
+})
+
+#define list_is_empty_named(list,prev,next) \
+ ((list) == NULL)
+
+#define list_get_head_named(list,prev,next) \
+ (list)
+
+#define list_get_tail_named(list,prev,next) \
+ ((list)?((list)->prev):NULL)
+
+/* Internal macro : insert before the head == insert at tail */
+#define __list_insert_atleft_named(before_this,item,prev,next) ({ \
+ (before_this)->prev->next = (item); \
+ (item)->prev = (before_this)->prev; \
+ (before_this)->prev = (item); \
+ (item)->next = (before_this); \
+})
+
+/* @note Before_this and item are expected to be valid ! */
+#define list_insert_before_named(list,before_this,item,prev,next) ({ \
+ __list_insert_atleft_named(before_this,item,prev,next); \
+ if ((list) == (before_this)) (list) = (item); \
+})
+
+/** @note After_this and item are expected to be valid ! */
+#define list_insert_after_named(list,after_this,item,prev,next) ({ \
+ (after_this)->next->prev = (item); \
+ (item)->next = (after_this)->next; \
+ (after_this)->next = (item); \
+ (item)->prev = (after_this); \
+})
+
+#define list_add_head_named(list,item,prev,next) ({ \
+ if (list) \
+ list_insert_before_named(list,list,item,prev,next); \
+ else \
+ list_singleton_named(list,item,prev,next); \
+ (list) = (item); \
+})
+
+#define list_add_tail_named(list,item,prev,next) ({ \
+ if (list) \
+ __list_insert_atleft_named(list,item,prev,next); \
+ else \
+ list_singleton_named(list,item,prev,next); \
+})
+
+/** @note NO check whether item really is in list ! */
+#define list_delete_named(list,item,prev,next) ({ \
+ if ( ((item)->next == (item)) && ((item)->prev == (item)) ) \
+ (item)->next = (item)->prev = (list) = NULL; \
+ else { \
+ (item)->prev->next = (item)->next; \
+ (item)->next->prev = (item)->prev; \
+ if ((item) == (list)) (list) = (item)->next; \
+ (item)->prev = (item)->next = NULL; \
+ } \
+})
+
+#define list_pop_head_named(list,prev,next) ({ \
+ typeof(list) __ret_elt = (list); \
+ list_delete_named(list,__ret_elt,prev,next); \
+ __ret_elt; })
+
+/** Loop statement that iterates through all of its elements, from
+ head to tail */
+#define list_foreach_forward_named(list,iterator,nb_elements,prev,next) \
+ for (nb_elements=0, (iterator) = (list) ; \
+ (iterator) && (!nb_elements || ((iterator) != (list))) ; \
+ nb_elements++, (iterator) = (iterator)->next )
+
+/** Loop statement that iterates through all of its elements, from
+ tail back to head */
+#define list_foreach_backward_named(list,iterator,nb_elements,prev,next) \
+ for (nb_elements=0, (iterator) = list_get_tail_named(list,prev,next) ; \
+ (iterator) && (!nb_elements || \
+ ((iterator) != list_get_tail_named(list,prev,next))) ; \
+ nb_elements++, (iterator) = (iterator)->prev )
+
+#define list_foreach_named list_foreach_forward_named
+
+/** True when we exitted early from the foreach loop (ie break) */
+#define list_foreach_early_break(list,iterator,nb_elements) \
+ ((list) && ( \
+ ((list) != (iterator)) || \
+ ( ((list) == (iterator)) && (nb_elements == 0)) ))
+
+/** Loop statement that also removes the item at each iteration */
+#define list_collapse_named(list,iterator,prev,next) \
+ for ( ; ({ ((iterator) = (list)) ; \
+ if (list) list_delete_named(list,iterator,prev,next) ; \
+ (iterator); }) ; )
+
+
+/*
+ * the same macros : assume that the prev and next fields are really
+ * named "prev" and "next"
+ */
+
+#define list_init(list) \
+ list_init_named(list,prev,next)
+
+#define list_singleton(list,item) \
+ list_singleton_named(list,item,prev,next)
+
+#define list_is_empty(list) \
+ list_is_empty_named(list,prev,next)
+
+#define list_get_head(list) \
+ list_get_head_named(list,prev,next) \
+
+#define list_get_tail(list) \
+ list_get_tail_named(list,prev,next) \
+
+/* @note Before_this and item are expected to be valid ! */
+#define list_insert_after(list,after_this,item) \
+ list_insert_after_named(list,after_this,item,prev,next)
+
+/* @note After_this and item are expected to be valid ! */
+#define list_insert_before(list,before_this,item) \
+ list_insert_before_named(list,before_this,item,prev,next)
+
+#define list_add_head(list,item) \
+ list_add_head_named(list,item,prev,next)
+
+#define list_add_tail(list,item) \
+ list_add_tail_named(list,item,prev,next)
+
+/* @note NO check whether item really is in list ! */
+#define list_delete(list,item) \
+ list_delete_named(list,item,prev,next)
+
+#define list_pop_head(list) \
+ list_pop_head_named(list,prev,next)
+
+#define list_foreach_forward(list,iterator,nb_elements) \
+ list_foreach_forward_named(list,iterator,nb_elements,prev,next)
+
+#define list_foreach_backward(list,iterator,nb_elements) \
+ list_foreach_backward_named(list,iterator,nb_elements,prev,next)
+
+#define list_foreach list_foreach_forward
+
+#define list_collapse(list,iterator) \
+ list_collapse_named(list,iterator,prev,next)
+
+#endif /* _SOS_LIST_H_ */
diff --git a/sos-code-article3/sos/macros.h b/sos-code-article3/sos/macros.h
new file mode 100644
index 0000000..b08f081
--- /dev/null
+++ b/sos-code-article3/sos/macros.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2004 The KOS Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_MACROS_H_
+#define _SOS_MACROS_H_
+
+/** Align on a boundary (MUST be a power of 2), so that return value <= val */
+#define SOS_ALIGN_INF(val,boundary) \
+ (((unsigned)(val)) & (~((boundary)-1)))
+
+/** Align on a boundary (MUST be a power of 2), so that return value >= val */
+#define SOS_ALIGN_SUP(val,boundary) \
+ ({ unsigned int __bnd=(boundary); \
+ (((((unsigned)(val))-1) & (~(__bnd - 1))) + __bnd); })
+
+/**
+ * @return TRUE if val is a power of 2.
+ * @note val is evaluated multiple times
+ */
+#define SOS_IS_POWER_OF_2(val) \
+ ((((val) - 1) & (val)) == 0)
+
+#endif /* _SOS_MACROS_H_ */
diff --git a/sos-code-article3/sos/main.c b/sos-code-article3/sos/main.c
new file mode 100644
index 0000000..3cce935
--- /dev/null
+++ b/sos-code-article3/sos/main.c
@@ -0,0 +1,236 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* Include definitions of the multiboot standard */
+#include <bootstrap/multiboot.h>
+#include <hwcore/idt.h>
+#include <hwcore/gdt.h>
+#include <hwcore/irq.h>
+#include <hwcore/exception.h>
+#include <hwcore/i8254.h>
+#include <sos/list.h>
+#include <sos/physmem.h>
+#include <sos/klibc.h>
+#include <sos/assert.h>
+#include <drivers/x86_videomem.h>
+#include <drivers/bochs.h>
+
+
+/* Helper function to display each bits of a 32bits integer on the
+ screen as dark or light carrets */
+static void display_bits(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ sos_ui32_t integer)
+{
+ int i;
+ /* Scan each bit of the integer, MSb first */
+ for (i = 31 ; i >= 0 ; i--)
+ {
+ /* Test if bit i of 'integer' is set */
+ int bit_i = (integer & (1 << i));
+ /* Ascii 219 => dark carret, Ascii 177 => light carret */
+ unsigned char ascii_code = bit_i?219:177;
+ sos_x86_videomem_putchar(row, col++,
+ attribute,
+ ascii_code);
+ }
+}
+
+
+/* Clock IRQ handler */
+static void clk_it(int intid)
+{
+ static sos_ui32_t clock_count = 0;
+
+ display_bits(0, 48,
+ SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
+ clock_count);
+ clock_count++;
+
+}
+
+#define MY_PPAGE_NUM_INT 511
+struct my_ppage
+{
+ sos_ui32_t before[MY_PPAGE_NUM_INT];
+ struct my_ppage *prev, *next;
+ sos_ui32_t after[MY_PPAGE_NUM_INT];
+}; /* sizeof() Must be <= 4kB */
+
+static void test_physmem()
+{
+ /* We place the pages we did allocate here */
+ struct my_ppage *ppage_list, *my_ppage;
+ sos_count_t num_alloc_ppages = 0, num_free_ppages = 0;
+
+ ppage_list = NULL;
+ while ((my_ppage = (struct my_ppage*)sos_physmem_ref_physpage_new(FALSE))
+ != NULL)
+ {
+ int i;
+ num_alloc_ppages++;
+
+ /* Print the allocation status */
+ sos_x86_videomem_printf(2, 0,
+ SOS_X86_VIDEO_FG_YELLOW
+ | SOS_X86_VIDEO_BG_BLUE,
+ "Could allocate %d pages ",
+ num_alloc_ppages);
+
+ /* We fill this page with its address */
+ for (i = 0 ; i < MY_PPAGE_NUM_INT ; i++)
+ my_ppage->before[i] = my_ppage->after[i] = (sos_ui32_t)my_ppage;
+
+ /* We add this page at the tail of our list of ppages */
+ list_add_tail(ppage_list, my_ppage);
+ }
+
+ /* Now we release these pages in FIFO order */
+ while ((my_ppage = list_pop_head(ppage_list)) != NULL)
+ {
+ /* We make sure this page was not overwritten by any unexpected
+ value */
+ int i;
+ for (i = 0 ; i < MY_PPAGE_NUM_INT ; i++)
+ {
+ /* We don't get what we expect ! */
+ if ((my_ppage->before[i] != (sos_ui32_t)my_ppage)
+ || (my_ppage->after[i] != (sos_ui32_t)my_ppage))
+ {
+ /* STOP ! */
+ sos_x86_videomem_putstring(20, 0,
+ SOS_X86_VIDEO_FG_LTRED
+ | SOS_X86_VIDEO_BG_BLUE,
+ "Page overwritten");
+ return;
+ }
+ }
+
+ /* Release the descriptor */
+ if (sos_physmem_unref_physpage((sos_paddr_t)my_ppage) < 0)
+ {
+ /* STOP ! */
+ sos_x86_videomem_putstring(20, 0,
+ SOS_X86_VIDEO_FG_LTRED
+ | SOS_X86_VIDEO_BG_BLUE,
+ "Cannot release page");
+ return;
+ }
+
+ /* Print the deallocation status */
+ num_free_ppages ++;
+ sos_x86_videomem_printf(2, 0,
+ SOS_X86_VIDEO_FG_YELLOW
+ | SOS_X86_VIDEO_BG_BLUE,
+ "Could free %d pages ",
+ num_free_ppages);
+ }
+
+ /* Print the overall stats */
+ sos_x86_videomem_printf(2, 0,
+ SOS_X86_VIDEO_FG_LTGREEN
+ | SOS_X86_VIDEO_BG_BLUE,
+ "Could allocate %d bytes, could free %d bytes ",
+ num_alloc_ppages << SOS_PAGE_SHIFT,
+ num_free_ppages << SOS_PAGE_SHIFT);
+
+ SOS_ASSERT_FATAL(num_alloc_ppages == num_free_ppages);
+}
+
+
+/* The C entry point of our operating system */
+void sos_main(unsigned long magic, unsigned long addr)
+{
+ unsigned i;
+ sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr;
+
+ /* Grub sends us a structure, called multiboot_info_t with a lot of
+ precious informations about the system, see the multiboot
+ documentation for more information. */
+ multiboot_info_t *mbi;
+ mbi = (multiboot_info_t *) addr;
+
+ /* Setup bochs and console, and clear the console */
+ sos_bochs_setup();
+
+ sos_x86_videomem_setup();
+ sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
+
+ /* Greetings from SOS */
+ if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
+ /* Loaded with Grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
+ "SOS", ',',
+ (unsigned)(mbi->mem_upper >> 10) + 1,
+ (unsigned)mbi->mem_upper);
+ else
+ /* Not loaded with grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome to SOS");
+
+ sos_bochs_putstring("Message in a bochs\n");
+
+ /* Setup CPU segmentation and IRQ subsystem */
+ sos_gdt_setup();
+ sos_idt_setup();
+
+ /* Setup SOS IRQs and exceptions subsystem */
+ sos_exceptions_setup();
+ sos_irq_setup();
+
+ /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */
+ sos_i8254_set_frequency(100);
+
+
+ /* We need a multiboot-compliant boot loader to get the size of the RAM */
+ if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
+ {
+ sos_x86_videomem_putstring(20, 0,
+ SOS_X86_VIDEO_FG_LTRED
+ | SOS_X86_VIDEO_BG_BLUE
+ | SOS_X86_VIDEO_FG_BLINKING,
+ "I'm not loaded with Grub !");
+ /* STOP ! */
+ for (;;)
+ continue;
+ }
+
+ /* Binding some HW interrupts and exceptions to software routines */
+ sos_irq_set_routine(SOS_IRQ_TIMER,
+ clk_it);
+ /* Enabling the HW interrupts here, this will make the timer HW
+ interrupt call our clk_it handler */
+ asm volatile ("sti\n");
+ /* Multiboot says: "The value returned for upper memory is maximally
+ the address of the first upper memory hole minus 1 megabyte.". It
+ also adds: "It is not guaranteed to be this value." aka "YMMV" ;) */
+ sos_physmem_setup((mbi->mem_upper<<10) + (1<<20),
+ & sos_kernel_core_base_paddr,
+ & sos_kernel_core_top_paddr);
+ test_physmem();
+
+ /* An operatig system never ends */
+ for (;;)
+ continue;
+
+ return;
+}
diff --git a/sos-code-article3/sos/physmem.c b/sos-code-article3/sos/physmem.c
new file mode 100644
index 0000000..99cffb7
--- /dev/null
+++ b/sos-code-article3/sos/physmem.c
@@ -0,0 +1,269 @@
+/* Copyright (C) 2004 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <sos/list.h>
+#include <sos/macros.h>
+#include <sos/assert.h>
+#include <sos/klibc.h>
+
+#include "physmem.h"
+
+/** A descriptor for a physical page in SOS */
+struct physical_page_descr
+{
+ /** The physical base address for the page */
+ sos_paddr_t paddr;
+
+ /** The reference count for this physical page. > 0 means that the
+ page is in the used list. */
+ sos_count_t ref_cnt;
+
+ /** The other pages on the list (used, free) */
+ struct physical_page_descr *prev, *next;
+};
+
+/** These are some markers present in the executable file (see sos.lds) */
+extern char __b_kernel, __e_kernel;
+
+/** The array of ppage descriptors will be located at this address */
+#define PAGE_DESCR_ARRAY_ADDR \
+ SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kernel))
+static struct physical_page_descr * physical_page_descr_array;
+
+/** The list of physical pages currently available */
+static struct physical_page_descr *free_ppage;
+
+/** The list of physical pages currently in use */
+static struct physical_page_descr *used_ppage;
+
+/** We will store here the interval of valid physical addresses */
+static sos_paddr_t physmem_base, physmem_top;
+
+/** We store the number of pages used/free */
+static sos_count_t physmem_total_pages, physmem_used_pages;
+
+sos_ret_t sos_physmem_setup(sos_size_t ram_size,
+ /* out */sos_paddr_t *kernel_core_base,
+ /* out */sos_paddr_t *kernel_core_top)
+{
+ /* The iterator over the page descriptors */
+ struct physical_page_descr *ppage_descr;
+
+ /* The iterator over the physical addresses */
+ sos_paddr_t ppage_addr;
+
+ /* Make sure ram size is aligned on a page boundary */
+ ram_size = SOS_PAGE_ALIGN_INF(ram_size);/* Yes, we may lose at most a page */
+
+ /* Reset the used/free page lists before building them */
+ free_ppage = used_ppage = NULL;
+ physmem_total_pages = physmem_used_pages = 0;
+
+ /* Make sure that there is enough memory to store the array of page
+ descriptors */
+ *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_paddr_t)(& __b_kernel));
+ *kernel_core_top
+ = PAGE_DESCR_ARRAY_ADDR
+ + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_PAGE_SHIFT)
+ * sizeof(struct physical_page_descr));
+ if (*kernel_core_top > ram_size)
+ return -SOS_ENOMEM;
+
+ /* Page 0-4kB is not available in order to return address 0 as a
+ means to signal "no page available" */
+ physmem_base = SOS_PAGE_SIZE;
+ physmem_top = ram_size;
+
+ /* Setup the page descriptor arrray */
+ physical_page_descr_array
+ = (struct physical_page_descr*)PAGE_DESCR_ARRAY_ADDR;
+
+ /* Scan the list of physical pages */
+ for (ppage_addr = 0,
+ ppage_descr = physical_page_descr_array ;
+ ppage_addr < physmem_top ;
+ ppage_addr += SOS_PAGE_SIZE,
+ ppage_descr ++)
+ {
+ enum { PPAGE_MARK_RESERVED, PPAGE_MARK_FREE,
+ PPAGE_MARK_KERNEL, PPAGE_MARK_HWMAP } todo;
+
+ memset(ppage_descr, 0x0, sizeof(struct physical_page_descr));
+
+ /* Init the page descriptor for this page */
+ ppage_descr->paddr = ppage_addr;
+
+ /* Reserved : 0 ... base */
+ if (ppage_addr < physmem_base)
+ todo = PPAGE_MARK_RESERVED;
+
+ /* Free : base ... BIOS */
+ else if ((ppage_addr >= physmem_base)
+ && (ppage_addr < BIOS_N_VIDEO_START))
+ todo = PPAGE_MARK_FREE;
+
+ /* Used : BIOS */
+ else if ((ppage_addr >= BIOS_N_VIDEO_START)
+ && (ppage_addr < BIOS_N_VIDEO_END))
+ todo = PPAGE_MARK_HWMAP;
+
+ /* Free : BIOS ... kernel */
+ else if ((ppage_addr >= BIOS_N_VIDEO_END)
+ && (ppage_addr < (sos_paddr_t) (& __b_kernel)))
+ todo = PPAGE_MARK_FREE;
+
+ /* Used : Kernel code/data/bss + physcal page descr array */
+ else if ((ppage_addr >= *kernel_core_base)
+ && (ppage_addr < *kernel_core_top))
+ todo = PPAGE_MARK_KERNEL;
+
+ /* Free : first page of descr ... end of RAM */
+ else
+ todo = PPAGE_MARK_FREE;
+
+ /* Actually does the insertion in the used/free page lists */
+ physmem_total_pages ++;
+ switch (todo)
+ {
+ case PPAGE_MARK_FREE:
+ ppage_descr->ref_cnt = 0;
+ list_add_head(free_ppage, ppage_descr);
+ break;
+
+ case PPAGE_MARK_KERNEL:
+ case PPAGE_MARK_HWMAP:
+ ppage_descr->ref_cnt = 1;
+ list_add_head(used_ppage, ppage_descr);
+ physmem_used_pages ++;
+ break;
+
+ default:
+ /* Reserved page: nop */
+ break;
+ }
+ }
+
+ return SOS_OK;
+}
+
+
+sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block)
+{
+ struct physical_page_descr *ppage_descr;
+
+ if (! free_ppage)
+ return (sos_paddr_t)NULL;
+
+ /* Retrieve a page in the free list */
+ ppage_descr = list_pop_head(free_ppage);
+
+ /* The page is assumed not to be already used */
+ SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);
+
+ /* Mark the page as used (this of course sets the ref count to 1) */
+ ppage_descr->ref_cnt ++;
+
+ /* Put the page in the used list */
+ list_add_tail(used_ppage, ppage_descr);
+ physmem_used_pages ++;
+
+ return ppage_descr->paddr;
+}
+
+
+/**
+ * Helper function to get the physical page descriptor for the given
+ * physical page address.
+ *
+ * @return NULL when out-of-bounds or non-page-aligned
+ */
+inline static struct physical_page_descr *
+get_page_descr_at_paddr(sos_paddr_t ppage_paddr)
+{
+ /* Don't handle non-page-aligned addresses */
+ if (ppage_paddr & SOS_PAGE_MASK)
+ return NULL;
+
+ /* Don't support out-of-bounds requests */
+ if ((ppage_paddr < physmem_base) || (ppage_paddr >= physmem_top))
+ return NULL;
+
+ return physical_page_descr_array + (ppage_paddr >> SOS_PAGE_SHIFT);
+}
+
+
+sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr)
+{
+ struct physical_page_descr *ppage_descr
+ = get_page_descr_at_paddr(ppage_paddr);
+
+ if (! ppage_descr)
+ return -SOS_EINVAL;
+
+ /* Increment the reference count for the page */
+ ppage_descr->ref_cnt ++;
+
+ /* If the page is newly referenced (ie we are the only owners of the
+ page => ref cnt == 1), transfer it in the used pages list */
+ if (ppage_descr->ref_cnt == 1)
+ {
+ list_delete(free_ppage, ppage_descr);
+ list_add_tail(used_ppage, ppage_descr);
+ physmem_used_pages ++;
+
+ /* The page is newly referenced */
+ return FALSE;
+ }
+
+ /* The page was already referenced by someone */
+ return TRUE;
+}
+
+
+sos_ret_t
+sos_physmem_unref_physpage(sos_paddr_t ppage_paddr)
+{
+ /* By default the return value indicates that the page is still
+ used */
+ sos_ret_t retval = FALSE;
+
+ struct physical_page_descr *ppage_descr
+ = get_page_descr_at_paddr(ppage_paddr);
+
+ if (! ppage_descr)
+ return -SOS_EINVAL;
+
+ /* Don't do anything if the page is not in the used list */
+ if (ppage_descr->ref_cnt <= 0)
+ return -SOS_EINVAL;
+
+ /* Unreference the page, and, when no mapping is active anymore, put
+ the page in the free list */
+ ppage_descr->ref_cnt--;
+ if (ppage_descr->ref_cnt <= 0)
+ {
+ /* Transfer the page, considered USED, to the free list */
+ list_delete(used_ppage, ppage_descr);
+ physmem_used_pages --;
+ list_add_head(free_ppage, ppage_descr);
+
+ /* Indicate that the page is now unreferenced */
+ retval = TRUE;
+ }
+
+ return retval;
+}
diff --git a/sos-code-article3/sos/physmem.h b/sos-code-article3/sos/physmem.h
new file mode 100644
index 0000000..8b5d997
--- /dev/null
+++ b/sos-code-article3/sos/physmem.h
@@ -0,0 +1,119 @@
+/* Copyright (C) 2004 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_PHYSMEM_H_
+#define _SOS_PHYSMEM_H_
+
+/**
+ * @file physmem.h
+ *
+ * Physical pages of memory
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+#include <sos/macros.h>
+
+/** The size of a physical page (arch-dependent) */
+#define SOS_PAGE_SIZE (4*1024)
+
+/** The corresponding shift */
+#define SOS_PAGE_SHIFT 12 /* 4 kB = 2^12 B */
+
+/** The corresponding mask */
+#define SOS_PAGE_MASK ((1<<12) - 1)
+
+#define SOS_PAGE_ALIGN_INF(val) \
+ SOS_ALIGN_INF((val), SOS_PAGE_SIZE)
+#define SOS_PAGE_ALIGN_SUP(val) \
+ SOS_ALIGN_SUP((val), SOS_PAGE_SIZE)
+
+
+/**
+ * This is the reserved physical interval for the x86 video memory and
+ * BIOS area. In physmem.c, we have to mark this area as "used" in
+ * order to prevent from allocating it. And in paging.c, we'd better
+ * map it in virtual space if we really want to be able to print to
+ * the screen (for debugging purpose, at least): for this, the
+ * simplest is to identity-map this area in virtual space (note
+ * however that this mapping could also be non-identical).
+ */
+#define BIOS_N_VIDEO_START 0xa0000
+#define BIOS_N_VIDEO_END 0x100000
+
+
+/**
+ * Initialize the physical memory subsystem, for the physical area [0,
+ * ram_size). This routine takes into account the BIOS and video
+ * areas, to prevent them from future allocations.
+ *
+ * @param ram_size The size of the RAM that will be managed by this subsystem
+ *
+ * @param kernel_core_base The lowest address for which the kernel
+ * assumes identity mapping (ie virtual address == physical address)
+ * will be stored here
+ *
+ * @param kernel_core_top The top address for which the kernel
+ * assumes identity mapping (ie virtual address == physical address)
+ * will be stored here
+ */
+sos_ret_t sos_physmem_setup(sos_size_t ram_size,
+ /* out */sos_paddr_t *kernel_core_base,
+ /* out */sos_paddr_t *kernel_core_top);
+
+/**
+ * Retrieve the total number of pages, and the number of free pages
+ */
+sos_ret_t sos_physmem_get_state(/* out */sos_count_t *total_ppages,
+ /* out */sos_count_t *used_ppages);
+
+
+/**
+ * Get a free page.
+ *
+ * @return The (physical) address of the (physical) page allocated, or
+ * NULL when none currently available.
+ *
+ * @param can_block TRUE if the function is allowed to block
+ * @note The page returned has a reference count equal to 1.
+ */
+sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block);
+
+
+/**
+ * Increment the reference count of a given physical page. Useful for
+ * VM code which tries to map a precise physical address.
+ *
+ * @return TRUE when the page was previously in use, FALSE when the
+ * page was previously in the free list, <0 when the page address is
+ * invalid.
+ */
+sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr);
+
+
+/**
+ * Decrement the reference count of the given physical page. When this
+ * reference count reaches 0, the page is marked free, ie is available
+ * for future sos_physmem_get_physpage()
+ *
+ * @return FALSE when the page is still in use, TRUE when the page is now
+ * unreferenced, <0 when the page address is invalid
+ */
+sos_ret_t sos_physmem_unref_physpage(sos_paddr_t ppage_paddr);
+
+
+#endif /* _SOS_PHYSMEM_H_ */
diff --git a/sos-code-article3/sos/types.h b/sos-code-article3/sos/types.h
new file mode 100644
index 0000000..02d9f6d
--- /dev/null
+++ b/sos-code-article3/sos/types.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_TYPES_H_
+#define _SOS_TYPES_H_
+
+/**
+ * @file types.h
+ *
+ * SOS basic types definition
+ */
+
+/** Physical address */
+typedef unsigned int sos_paddr_t;
+
+/** Generic virtual address (kernel or user) */
+typedef unsigned int sos_vaddr_t;
+
+/** Memory size of an object (positive) */
+typedef unsigned int sos_size_t;
+/** Generic count of objects */
+typedef unsigned int sos_count_t;
+
+/** Low-level sizes */
+typedef unsigned long int sos_ui32_t; /* 32b unsigned */
+typedef unsigned short int sos_ui16_t; /* 16b unsigned */
+typedef unsigned char sos_ui8_t; /* 8b unsigned */
+
+typedef enum { FALSE=0, TRUE } sos_bool_t;
+
+/** Not a proper type, but highly useful with basic type
+ manipulations */
+#define NULL ((void*)0)
+
+#endif /* _SOS_TYPES_H_ */
diff --git a/sos-code-article3/support/build_image.sh b/sos-code-article3/support/build_image.sh
new file mode 100755
index 0000000..43929cd
--- /dev/null
+++ b/sos-code-article3/support/build_image.sh
@@ -0,0 +1,215 @@
+#!/bin/sh
+# Copyright (C) 2003, David Decotigny
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# 1) What does it do ?
+#
+# 1) Check where Grub is installed (lookup_grub)
+# 2) Assign some local variables using the shell script arguments.
+# a) Argument 1 : the destination (either a file or a drive, like a:)
+# b) Argument 2 : the loader (i.e kernel)
+# c) Argument 3 : options passed to the loader
+# d) Argument 4 : the modules (that can be loaded optionally by Grub)
+# 3) Test whether destination is a drive or a file
+# 4) Create the directory structure inside the drive
+# 5) Copy the loader in the drive
+# 6) Generate the 'menu.txt' file used by Grub to generate the boot menu
+# 7) Copy all modules
+# 8) Copy the menu.txt file
+#
+# 2) Why is it so complex ?
+# Because it must support various Grub/mtools installations and versions
+#
+# In fact, this shell script is used in the KOS (kos.enix.org)
+# project. This operating system consists in a loader and many many
+# modules that are linked together at boot time. It is much more
+# complex that a simple monolithic kernel.
+#
+# For your simple monolithic kernel, you only need to give argument 1
+# and 2.
+
+print_usage () {
+ echo "Usage: $0 [X:|image] path/to/loader option path/to/modules..."
+ echo " where X: is a valid floppy drive on your computer"
+ echo " where image is any file name"
+ exit 1
+}
+
+grub_dirs_common="/usr/local/share/grub/i386-freebsd /usr/local/share/grub/i386-pc /usr/share/grub/i386-pc /usr/lib/grub/i386-pc /usr/local/grub /usr/share/grub/i386-redhat /usr/local/src/grub-0.5.94 $HOME/share/grub/i386-pc/"
+sbin_grub_path="/usr/local/sbin /usr/sbin /sbin $HOME/sbin"
+
+PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
+export PATH
+
+MTOOLSRC=mtoolsrc
+export MTOOLSRC
+
+# Redefined variables
+FLOPPY_DRIVE=A:
+IMG_FNAME=fd.img
+
+##
+## Format disk image
+##
+init_image () {
+ echo "Initialize disk image $IMG_FILE..."
+ if [ ! -f $IMG_FNAME ] ; then
+ dd if=/dev/zero of=$IMG_FNAME bs=18k count=80 1>/dev/null 2>&1
+ fi
+
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M filter" > $MTOOLSRC
+
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M" > $MTOOLSRC
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\"" > $MTOOLSRC
+ mformat U:
+ fi
+ fi
+}
+
+
+##
+## Format (real) floppy disk
+##
+init_floppy () {
+ echo "Formatting floppy..."
+ mformat $FLOPPY_DRIVE || exit 1
+}
+
+
+lookup_grub () {
+ # Look for a correct GRUBDIR
+ for d in $grub_dirs_common ; do
+ if [ -d $d ] ; then
+ GRUBDIR=$d
+ break
+ fi
+ done
+
+ # Try to guess with locate
+ if [ ! -d "$GRUBDIR" ] ; then
+ GRUBDIR=`locate stage2 | head -1 | xargs dirname 2>/dev/null`
+ fi
+
+ # Look for a correct sbin/grub
+ for d in $sbin_grub_path ; do
+ if [ -x $d/grub ] ; then
+ SBIN_GRUB=$d/grub
+ break
+ fi
+ done
+
+ if [ -d "$GRUBDIR" -a -x "$SBIN_GRUB" ] ; then
+ echo "Found correct grub installation in $GRUBDIR"
+ echo "Found correct /sbin/grub at $SBIN_GRUB"
+ else
+ echo "Couldn't find a correct grub installation."
+ exit 1
+ fi
+}
+
+##
+## setup_disk [drive]
+## => setup disk directory structure / copy files
+##
+setup_disk () {
+ echo "Setup destination disk..."
+
+ mmd $1/boot
+ mmd $1/boot/grub
+
+ if [ -d $GRUBDIR/stage1 ] ; then
+ mcopy $GRUBDIR/stage1/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2/stage2 $1/boot/grub/
+ else
+ mcopy $GRUBDIR/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2 $1/boot/grub/
+ fi
+ mmd $1/system
+ mmd $1/modules
+
+ $SBIN_GRUB --batch <<EOT 1>/dev/null 2>/dev/null || exit 1
+device (fd0) $IMG_FNAME
+install (fd0)/boot/grub/stage1 (fd0) (fd0)/boot/grub/stage2 p (fd0)/boot/grub/menu.txt
+quit
+EOT
+}
+
+
+
+#################################################
+## Real start
+##
+#[ "$#" -lt 3 ] && print_usage
+
+lookup_grub
+
+dest="$1" ; shift
+loader_fname="$1" ; shift
+options="$1" ; shift
+modules="$*"
+
+# Init destination disk
+case x$dest in
+ x*:)
+ drive=$dest
+ IMG_FNAME=$dest
+ FLOPPY_DRIVE=$dest
+ init_floppy
+ ;;
+ x*)
+ drive=U:
+ IMG_FNAME=$dest
+ init_image
+ ;;
+esac
+
+# Create directory structure
+setup_disk $drive
+
+# Copy the loader
+mcopy -bo $loader_fname $drive/system/`basename $loader_fname`
+
+# Generate the menu.txt file
+rm -f menu.txt
+cat <<EOF > menu.txt
+timeout 0
+default 0
+title Simple OS
+root (fd0)
+kernel /system/`basename $loader_fname` $options
+EOF
+
+# Copy the modules
+for f in $modules ; do
+ if [ ! -f $f ] ; then
+ echo "ERROR: module $f not correctly compiled in."
+ exit 1
+ fi
+ if ! mcopy -bo $f $drive/modules/`basename $f` ; then
+ echo "ERROR: module $f could not be transferred to floppy."
+ exit 1
+ fi
+ echo module /modules/`basename $f` >> menu.txt
+done
+
+# Transfers the menu.txt file to floppy
+mcopy -bo menu.txt $drive/boot/grub/
diff --git a/sos-code-article3/support/sos.lds b/sos-code-article3/support/sos.lds
new file mode 100644
index 0000000..4d87061
--- /dev/null
+++ b/sos-code-article3/support/sos.lds
@@ -0,0 +1,107 @@
+/* Copyright (C) 2003, Thomas Petazzoni
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* We generate binary in the ELF format */
+OUTPUT_FORMAT("elf32-i386","elf32-i386","elf32-i386");
+
+/* The entry point is _start (defined in boot.S) */
+ENTRY(_start)
+
+/* The architecture is i386 */
+OUTPUT_ARCH("i386")
+
+SECTIONS
+{
+ /* our kernel is loaded at 0x200000 */
+ . = 0x200000;
+ __b_load = .;
+
+ /* the multiboot header MUST come early enough in the output
+ object file */
+ .multiboot :
+ {
+ /* The multiboot section (containing the multiboot header)
+ goes here */
+ *(.multiboot);
+
+ /*
+ * With the following line, we force this section to be
+ * allocated in the output file as soon as possible, no matter
+ * when the file containing the multiboot header (multiboot.S)
+ * is compiled. This is to conform to the multiboot spec, which
+ * says "The Multiboot header must be contained completely
+ * within the first 8192 bytes of the OS image, and must be
+ * longword (32-bit) aligned."
+ */
+ LONG(0);
+ }
+
+ /* Defines a symbol '__b_kernel to mark the start of the kernel
+ code/data */
+ . = ALIGN(4096);
+ __b_kernel = .;
+
+ /* Beginning of the text section */
+ .text ALIGN(4096) :
+ {
+ /* This section includes the code */
+ *(.text*)
+ /* Defines the 'etext' and '_etext' at the end */
+ PROVIDE(etext = .);
+ PROVIDE(_etext = .);
+ }
+
+ /* Beginning of the data section */
+ .data . :
+ { *(.data*)
+ PROVIDE(edata = .);
+ PROVIDE(_edata = .);
+ }
+
+ /* Beginning of the read-only data section */
+ .rodata . :
+ { *(.rodata*)
+ PROVIDE(erodata = .);
+ PROVIDE(_erodata = .);
+ }
+ /* We take note of the end of the data to load */
+ __e_load = .;
+
+ /* Beginning of the BSS section (global uninitialized data) */
+ .bss SIZEOF(.rodata) + ADDR(.rodata) :
+ { *(.bss)
+ *(COMMON)
+ PROVIDE(ebss = .);
+ PROVIDE(_ebss = .);
+ }
+
+ /* We take note of the end of the kernel */
+ __e_kernel = .;
+
+ /* We don't care of the note, indent, comment, etc.. sections
+ generated by gcc */
+ /DISCARD/ :{
+ *(.note*)
+ *(.indent)
+ *(.comment)
+ *(.stab)
+ *(.stabstr)
+ }
+
+}
+
diff --git a/sos-code-article4/INSTALL b/sos-code-article4/INSTALL
new file mode 100644
index 0000000..7c7d619
--- /dev/null
+++ b/sos-code-article4/INSTALL
@@ -0,0 +1,118 @@
+
+ SOS: A Simple Operating System
+
+ Compilation/Installation/Test instructions
+
+
+Compilation
+===========
+
+IMPORTANT
+---------
+
+Don't forget to run 'make clean' before 'make' after you have modified
+any source or header file(s).
+
+
+On a x86 host where grub is correctly installed
+-----------------------------------------------
+
+Simply run 'make'
+
+
+On a non-x86 host (without grub of course !)
+--------------------------------------------
+
+See extra/README
+
+
+On an x86 host without Grub, or with a buggy Grub
+-------------------------------------------------
+
+See extra/README
+
+How do I know I have a buggy grub installation ? Answer: in the qemu
+PC emulator, Grub hangs while loading the kernel
+
+
+Installation
+============
+
+Nothing special to do besides compiling
+
+
+Test the SOS Kernel
+===================
+
+On a x86 real machine with Grub installed
+-----------------------------------------
+
+ 1st method
+ => Boot the sos.elf file (append 'kernel=<path_to>sos.elf' in the
+ menu.lst or type it on Grub's command line) from a hard disk, a
+ floppy, or from the network
+
+ 2nd method
+ => Copy the file 'fd.img' to a floppy and boot from it
+
+
+On a x86 real machine without Grub installed
+--------------------------------------------
+
+ 1st method
+ => see extra/README to compile with the grub floppy image we provide,
+ copy the file 'fd.img' to a floppy, and boot from it
+
+ 2nd method
+ => see extra/README to compile with the boot sector we provide (up to
+ article 2 only), copy the file 'extra/sos_bsect.img' to a floppy,
+ and boot from it
+
+
+Inside a PC emulator (x86 and non-x86 hosts)
+--------------------------------------------
+
+Tested on both the bochs emulator (x86/linux, sparc/solaris and
+ppc/linux hosts, 'apt-get install bochs-x vgabios' on debian
+testing/unstable), and the qemu system emulator (with libsdl
+installed: 'apt-get install libsdl1.2-dev' on debian
+testing/unstable).
+
+ 1/ Grub is installed on the host (x86 hosts only)
+ - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ bochs: boot from the file 'fd.img'. Example of a ~/.bochsrc:
+ floppya: 1_44=/home/d2/sos/fd.img, status=inserted
+ romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
+ vgaromimage: /usr/share/vgabios/vgabios.bin
+ megs:63 # 63 Mo de RAM
+
+ qemu: run 'qemu -fda fd.img'
+ If grub hangs while loading the kernel, please go to method 2/
+
+ 2/ Grub is not installed (all hosts)
+ - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the Grub floppy
+ image we provide, and:
+
+ bochs: boot from the file 'fd.img'
+
+ qemu: run 'qemu -fda fd.img'
+
+ 3/ Bonus: boot with the bootsector we provide (all hosts, up to art. 2 ONLY !)
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ See extra/README to generate a floppy image with the boot sector we
+ provide, and:
+
+ bochs: boot from the file 'extra/sos_bsect.img'
+
+ qemu: run 'qemu -fda extra/sos_qemu.img'
+
+ NOTE: After article 2, this way of booting is not supported: please
+ use the method 2/ above.
+
+
+--
+David Decotigny
diff --git a/sos-code-article4/LICENSE b/sos-code-article4/LICENSE
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/sos-code-article4/LICENSE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/sos-code-article4/Makefile b/sos-code-article4/Makefile
new file mode 100644
index 0000000..3a2282a
--- /dev/null
+++ b/sos-code-article4/Makefile
@@ -0,0 +1,45 @@
+CC=gcc
+CFLAGS = -Wall -nostdlib -nostdinc -ffreestanding -DKERNEL_SOS
+LDFLAGS = --warn-common
+OBJECTS = bootstrap/multiboot.o \
+ hwcore/idt.o hwcore/gdt.o \
+ hwcore/exception.o hwcore/exception_wrappers.o \
+ hwcore/irq.o hwcore/irq_wrappers.o hwcore/i8259.o \
+ hwcore/paging.o \
+ hwcore/i8254.o drivers/x86_videomem.o drivers/bochs.o \
+ sos/physmem.o sos/klibc.o sos/main.o
+
+KERNEL_OBJ = sos.elf
+MULTIBOOT_IMAGE = fd.img
+PWD := $(shell pwd)
+
+# Main target
+all: $(MULTIBOOT_IMAGE)
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ)
+ ./support/build_image.sh $@ $<
+
+$(KERNEL_OBJ): $(OBJECTS) ./support/sos.lds
+ $(LD) $(LDFLAGS) -T ./support/sos.lds -o $@ $(OBJECTS)
+ -nm -C $@ | cut -d ' ' -f 1,3 > sos.map
+
+-include .mkvars
+
+# Create objects from C source code
+%.o: %.c
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -o $@
+
+# Create objects from assembler (.S) source code
+%.o: %.S
+ $(CC) -I$(PWD) -c $< $(CFLAGS) -DASM_SOURCE=1 -o $@
+
+# Clean directory
+clean:
+ $(RM) *.img *.o mtoolsrc *~ menu.txt *.img *.elf *.bin *.map
+ $(RM) *.log *.out bochs*
+ $(RM) bootstrap/*.o bootstrap/*~
+ $(RM) drivers/*.o drivers/*~
+ $(RM) hwcore/*.o hwcore/*~
+ $(RM) sos/*.o sos/*~
+ $(RM) support/*~
+ $(RM) extra/*~
diff --git a/sos-code-article4/README b/sos-code-article4/README
new file mode 100644
index 0000000..efbbc89
--- /dev/null
+++ b/sos-code-article4/README
@@ -0,0 +1,90 @@
+
+ SOS: A Simple Operating System
+
+
+This is SOS, a Simple Operating System for i386-family
+processors. This is as simple as possible to show a way to program a
+basic Operating System on real common hardware (PC). The code should
+be easily readable and understandable thanks to frequent comments, and
+references to external documentation. We chose to implement the basic
+features of an OS, thus making design decisions targetting towards
+simplicity of understanding, covering most of the OS classical
+concepts, but not aiming at proposing yet another full-fledged
+competitive OS (Linux is quite good at it). However, for those who
+would like to propose some enhancements, we are open to any code
+suggestions (patches only, please). And yes, there might be bugs in
+the code, so please send us any bug report, and/or patches !
+
+The OS comes as a set of articles (in french) to be published in the
+journal "Linux Magazine France". Each month, the part of the code
+related to the current article's theme is released (see VERSION file),
+and the resulting OS can be successfully compiled and run, by booting
+it from a floppy on a real machine (tested AMD k7, Cyrix and Intel P4
+pentiums), or through an x86 emulator (bochs or qemu). The resulting
+OS is available as a multiboot compliant ELF kernel (sos.elf) and as a
+floppy image (fd.img). It provides a very very very basic demo whose
+aim is to understand how everything works, not to animate sprites on
+the screen with 5:1 dolby sound.
+
+The initial technical features and lack-of-features of the OS are:
+ - monolithic kernel, fully interruptible, non-preemptible (big kernel
+ lock), target machines = i386 PC or better
+ - compiles on any host where the gcc/binutils toolchain (target
+ i586-gnu) is available. Can be tested on real i486/pentium
+ hardware, or on any host that can run an i486/pentium PC emulator
+ (bochs or qemu)
+ - kernel loaded by grub, or by a sample bootsector (up to article 2
+ ONLY)
+ - clear separation of physical memory and virtual memory concepts,
+ even inside the kernel: no identity-mapping of the physical memory
+ inside the kernel (allows to move virtual mappings of kernel pages
+ at run-time, eg to free ISA DMA pages, and to avercome the 4G RAM
+ barrier)
+ - slab-type kernel memory allocation
+ - no swap, no reverse mapping
+ - VERY simple drivers: keyboard, x86 video memory, IDE disks
+ - logical devices: partitions, FAT filesystem, "hard-coded"
+ mountpoints only (~ MSDOS)
+ - no network stack
+ - user-level features: ELF loader (no shared libraries), processes,
+ user threads (kernel-level scheduling only), mmap API, basic VFS
+
+To understand where to look at for what, here is a brief description:
+ - Makefile: the (ONLY) makefile of the OS. Targets are basically
+ 'all' and 'clean'
+ - bootstrap/ directory: code to load the kernel. Both the stuff
+ needed for a multiboot-compliant loader (eg grub) AND a bootsector
+ are provided. The bootsector may only be used up to article 2.
+ - sos/ directory: the entry routine for the kernel (main.c), various
+ systemwide header files, a set of common useful C routines
+ ("nano-klibc"), and kernel subsystems (kernel memory management,
+ etc...)
+ - hwcore/ directory: Low-level CPU- and kernel-related routines
+ (interrupt/exception management, translation tables and segment
+ registers, ...)
+ - drivers/ directory: basic kernel drivers for various (non CPU)
+ devices (keyboard, x86 video memory, bochs 0xe9 port, ...). Used
+ mainly for debugging
+ - support/ directory: scripts and configuration files to build the
+ floppy images
+ - extra/ directory: a set of configuration files to be customized for
+ non-x86 host installations (yes, we primarily develop SOS on a ppc, for
+ the x86 target of course), or for grub-less installations. See
+ README file in this directory.
+
+The code is licensed under the terms of the GNU GPL version 2 (see
+LICENSE file).
+
+Enjoy !
+
+ David Decotigny, Thomas Petazzoni, the Kos team
+ http://sos.enix.org/
+ http://david.decotigny.free.fr/
+ http://kos.enix.org/~thomas/
+ http://kos.enix.org/
+
+
+--
+David Decotigny
+
+PS: Made with a Mac.
diff --git a/sos-code-article4/VERSION b/sos-code-article4/VERSION
new file mode 100644
index 0000000..146a301
--- /dev/null
+++ b/sos-code-article4/VERSION
@@ -0,0 +1,11 @@
+SOS -- Simple OS
+Copyright (C) 2003,2004 The SOS Team (David Decotigny & Thomas Petazzoni)
+
+Version "Article 4" -- Basic routines for x86 mmu supervision
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See the LICENSE file included in the distribution.
diff --git a/sos-code-article4/bootstrap/multiboot.S b/sos-code-article4/bootstrap/multiboot.S
new file mode 100644
index 0000000..4a7c65b
--- /dev/null
+++ b/sos-code-article4/bootstrap/multiboot.S
@@ -0,0 +1,74 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+
+/* The operating system is booted by Grub, so we almost have nothing
+ to do to boot it. We only have to conform to the Multiboot
+ standard, as defined by the Grub documentation */
+
+#define ASM 1
+/* The multiboot.h header contains a lot of multiboot standard
+ definitions */
+#include "multiboot.h"
+
+ /* The multiboot header itself. It must come first. */
+.section ".multiboot"
+ /* Multiboot header must be aligned on a 4-byte boundary */
+ .align 4
+multiboot_header:
+ /* magic= */ .long MULTIBOOT_HEADER_MAGIC
+ /* flags= */ .long MULTIBOOT_HEADER_FLAGS
+ /* checksum= */ .long -(MULTIBOOT_HEADER_MAGIC \
+ +MULTIBOOT_HEADER_FLAGS)
+ /* header_addr= */ .long multiboot_header
+ /* load_addr= */ .long __b_kernel
+ /* load_end_addr=*/ .long __e_load
+ /* bss_end_addr= */ .long __e_kernel
+ /* entry_addr= */ .long multiboot_entry
+
+/* Here is the beginning of the code of our operating system */
+.text
+
+.globl start, _start
+start:
+_start:
+multiboot_entry:
+ /* Set up a stack */
+ movl $(stack + MULTIBOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Set EFLAGS to 0 */
+ pushl $0
+ /* pop stack into the EFLAGS register */
+ popf
+
+ /* Push the magic and the address on the stack, so that they
+ will be the parameters of the cmain function */
+ pushl %ebx
+ pushl %eax
+
+ /* Call the cmain function (os.c) */
+ call EXT_C(sos_main)
+
+ /* Should never get there */
+loop:
+ hlt
+ jmp loop
+
+ /* Here is the stack */
+.comm stack, MULTIBOOT_STACK_SIZE
diff --git a/sos-code-article4/bootstrap/multiboot.h b/sos-code-article4/bootstrap/multiboot.h
new file mode 100644
index 0000000..bee676d
--- /dev/null
+++ b/sos-code-article4/bootstrap/multiboot.h
@@ -0,0 +1,129 @@
+#ifndef __MULTIBOOT_H__
+#define __MULTIBOOT_H__
+
+/* multiboot.h - the header for Multiboot */
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Macros. */
+
+/* The magic number for the Multiboot header. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* The flags for the Multiboot header. */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* The magic number passed by a Multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (16KB). */
+#define MULTIBOOT_STACK_SIZE 0x4000
+
+#define MULTIBOOT_CMDLINE 4
+#define MULTIBOOT_MODS 8
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* Do not include here in boot.S. */
+
+
+
+/* Types. */
+
+/* The Multiboot header. */
+typedef struct multiboot_header
+{
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* The symbol table for a.out. */
+typedef struct aout_symbol_table
+{
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* The section header table for ELF. */
+typedef struct elf_section_header_table
+{
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* The Multiboot information. */
+typedef struct multiboot_info
+{
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union
+ {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+ unsigned long drives_length;
+ unsigned long drives_addr;
+} multiboot_info_t;
+
+/* The module structure. */
+typedef struct module
+{
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* The memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map
+{
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+void dump_multiboot_info(multiboot_info_t *mbi);
+
+#endif /* ! ASM */
+
+#endif /* __MULTIBOOT_H__ */
diff --git a/sos-code-article4/drivers/bochs.c b/sos-code-article4/drivers/bochs.c
new file mode 100644
index 0000000..db18599
--- /dev/null
+++ b/sos-code-article4/drivers/bochs.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <hwcore/ioports.h>
+#include <sos/klibc.h>
+
+#include "bochs.h"
+
+/* This is a special hack that is only useful when running the
+ operating system under the Bochs emulator. */
+#define SOS_BOCHS_IOPORT 0xe9
+
+sos_ret_t sos_bochs_setup(void)
+{
+ return SOS_OK;
+}
+
+
+#define sos_bochs_putchar(chr) \
+ outb((chr), SOS_BOCHS_IOPORT)
+
+sos_ret_t sos_bochs_putstring(const char* str)
+{
+ for ( ; str && (*str != '\0') ; str++)
+ sos_bochs_putchar(*str);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes)
+{
+ unsigned c;
+
+#define BOCHS_PRTHEX(q) \
+ ({ unsigned char r; if ((q) >= 10) r='a'+(q)-10; \
+ else r='0'+(q); sos_bochs_putchar(r); })
+
+ switch (nbytes)
+ {
+ case 4:
+ c = (val >> 24) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 3:
+ c = (val >> 16) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 2:
+ c = (val >> 8) & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ case 1:
+ c = val & 0xff;
+ BOCHS_PRTHEX((c >> 4)&0xf);
+ BOCHS_PRTHEX(c&0xf);
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes)
+{
+ int offs;
+ for (offs = 0 ; offs < nbytes ; offs++)
+ {
+ const unsigned char *c;
+
+ if ((offs % 16) == 0)
+ {
+ sos_bochs_putstring("0x");
+ sos_bochs_puthex(offs, 4);
+ }
+
+ if ((offs % 8) == 0)
+ sos_bochs_putstring(" ");
+
+ c = (const unsigned char*)(addr + offs);
+ sos_bochs_puthex(*c, 1);
+ sos_bochs_putstring(" ");
+
+ if (((offs + 1) % 16) == 0)
+ sos_bochs_putstring("\n");
+ }
+
+ if (offs % 16)
+ sos_bochs_putstring("\n");
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_bochs_putstring(buff);
+}
diff --git a/sos-code-article4/drivers/bochs.h b/sos-code-article4/drivers/bochs.h
new file mode 100644
index 0000000..310b023
--- /dev/null
+++ b/sos-code-article4/drivers/bochs.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_BOCHS_H_
+#define _SOS_BOCHS_H_
+
+/**
+ * @file bochs.h
+ *
+ * If you compiled Bochs with the --enable-e9-hack, then any character
+ * printed to the 0xE9 I/O port is printed to the xterm that is
+ * running Bochs. This may appear to be a detail, but in fact, this
+ * functionnality is *VERY* precious for debugging purposes. This
+ * """driver""" handles this feature.
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+
+sos_ret_t sos_bochs_setup(void);
+
+sos_ret_t sos_bochs_putstring(const char* str);
+
+/** Print the least signficant 32 (nbytes == 4), 24 (nbytes == 3), 16
+ (nbytes == 2) or 8 (nbytes == 1) bits of val in hexadecimal. */
+sos_ret_t sos_bochs_puthex(unsigned val, int nbytes);
+
+/** hexdump-style pretty printing */
+sos_ret_t sos_bochs_hexdump(const void* addr, int nbytes);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_bochs_printf(const char *format, /* args */...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#endif
diff --git a/sos-code-article4/drivers/x86_videomem.c b/sos-code-article4/drivers/x86_videomem.c
new file mode 100644
index 0000000..cc4b79c
--- /dev/null
+++ b/sos-code-article4/drivers/x86_videomem.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <sos/klibc.h>
+#include <hwcore/ioports.h>
+
+#include "x86_videomem.h"
+
+/* The text video memory starts at address 0xB8000. Odd bytes are the
+ ASCII value of the character, even bytes are attribute for the
+ preceding character. */
+#define VIDEO 0xb8000
+
+
+/* Console screen size */
+#define LINES 25
+#define COLUMNS 80
+
+
+/** The structure of a character element in the video memory. @see
+ http://webster.cs.ucr.edu/AoA DOS edition chapter 23 */
+typedef struct {
+ unsigned char character;
+ unsigned char attribute;
+} __attribute__ ((packed)) x86_video_mem[LINES*COLUMNS];
+
+
+
+/** The base pointer for the video memory */
+static volatile x86_video_mem *video = (volatile x86_video_mem*)VIDEO;
+
+sos_ret_t sos_x86_videomem_setup(void)
+{
+ /*
+ * Hide cursor. @see Ralf Brown's interrupt (and port) list
+ * http://www-2.cs.cmu.edu/~ralf/files.html
+ */
+#define CRT_REG_INDEX 0x3d4
+#define CRT_REG_DATA 0x3d5
+
+ /* CRT index port => ask for access to register 0xa ("cursor
+ start") */
+ outb(0x0a, CRT_REG_INDEX);
+
+ /* (RBIL Tables 708 & 654) CRT Register 0xa => bit 5 = cursor OFF */
+ outb(1 << 5, CRT_REG_DATA);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute)
+{
+ /* Clears the screen */
+ int i;
+ for(i = 0 ; i < LINES*COLUMNS ; i++)
+ {
+ (*video)[i].character = 0;
+ (*video)[i].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ for ( ; str && *str && (video_offs < LINES*COLUMNS) ; str++, video_offs++)
+ {
+ (*video)[video_offs].character = (unsigned char)*str;
+ (*video)[video_offs].attribute = attribute;
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c)
+{
+ unsigned video_offs = row*COLUMNS + col;
+
+ if (video_offs >= LINES*COLUMNS)
+ return -SOS_EINVAL;
+
+ (*video)[video_offs].character = c;
+ (*video)[video_offs].attribute = attribute;
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+{
+ char buff[256];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buff, sizeof(buff), format, ap);
+ va_end(ap);
+
+ return sos_x86_videomem_putstring(row, col, attribute, buff);
+}
diff --git a/sos-code-article4/drivers/x86_videomem.h b/sos-code-article4/drivers/x86_videomem.h
new file mode 100644
index 0000000..31a9dfc
--- /dev/null
+++ b/sos-code-article4/drivers/x86_videomem.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_X86_VIDEOMEM_H_
+#define _SOS_X86_VIDEOMEM_H_
+
+/**
+ * @file x86_videomem.h
+ *
+ * On x86 PC platforms, the text mode screen memory (and CGA/EGA/VGA
+ * too) is mapped into physical memory. This file handles access to
+ * this screen, supposed to be set in text-mode, through this memory
+ * area. All the functions below print the characters directly to the
+ * memory, without interpreting the escaped characters (such as \n,
+ * \r...)
+ */
+
+#include <sos/errno.h>
+
+/**
+ * x86 video attributes
+ * See http://webster.cs.ucr.edu/AoA/DOS/ch23/CH23-1.html
+ */
+/* Normal and Dark/Light foreground */
+#define SOS_X86_VIDEO_FG_BLACK 0
+#define SOS_X86_VIDEO_FG_DKGRAY 8
+#define SOS_X86_VIDEO_FG_BLUE 1
+#define SOS_X86_VIDEO_FG_LTBLUE 9
+#define SOS_X86_VIDEO_FG_GREEN 2
+#define SOS_X86_VIDEO_FG_LTGREEN 10
+#define SOS_X86_VIDEO_FG_CYAN 3
+#define SOS_X86_VIDEO_FG_LTCYAN 11
+#define SOS_X86_VIDEO_FG_RED 4
+#define SOS_X86_VIDEO_FG_LTRED 12
+#define SOS_X86_VIDEO_FG_MAGENTA 5
+#define SOS_X86_VIDEO_FG_LTMAGENTA 13
+#define SOS_X86_VIDEO_FG_BROWN 6
+#define SOS_X86_VIDEO_FG_YELLOW 14
+#define SOS_X86_VIDEO_FG_LTGRAY 7
+#define SOS_X86_VIDEO_FG_WHITE 15
+/* Background */
+#define SOS_X86_VIDEO_BG_BLACK (0 << 4)
+#define SOS_X86_VIDEO_BG_BLUE (1 << 4)
+#define SOS_X86_VIDEO_BG_GREEN (2 << 4)
+#define SOS_X86_VIDEO_BG_CYAN (3 << 4)
+#define SOS_X86_VIDEO_BG_RED (4 << 4)
+#define SOS_X86_VIDEO_BG_MAGENTA (5 << 4)
+#define SOS_X86_VIDEO_BG_BROWN (6 << 4)
+#define SOS_X86_VIDEO_BG_LTGRAY (7 << 4)
+/* Blinking */
+#define SOS_X86_VIDEO_FG_BLINKING (1 << 7)
+
+
+/** Setup the video RAM mapping and clear the screen */
+sos_ret_t sos_x86_videomem_setup(void);
+
+/** Clears the screen and set the background color as given by
+ attribute */
+sos_ret_t sos_x86_videomem_cls(unsigned char attribute);
+
+/** Print the string on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putstring(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *str);
+
+/** Print the character on the scren with the given attribute. Does not
+ handle scrolling */
+sos_ret_t sos_x86_videomem_putchar(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ unsigned char c);
+
+/**
+ * Print the formatted string. Very restricted version of printf(3):
+ * 1/ can print max 255 chars, 2/ supports only %d/%i, %c, %s, %x
+ * without any support for flag charachters (eg %08x).
+ */
+sos_ret_t sos_x86_videomem_printf(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ const char *format, /* args */...)
+ __attribute__ ((format (printf, 4, 5)));
+
+#endif /* _SOS_X86_VIDEOMEM_H_ */
diff --git a/sos-code-article4/extra/Makefile b/sos-code-article4/extra/Makefile
new file mode 100644
index 0000000..f858aa6
--- /dev/null
+++ b/sos-code-article4/extra/Makefile
@@ -0,0 +1,40 @@
+OBJCOPY=objcopy
+
+all: sos_qemu.img
+
+-include ../.mkvars
+
+# The image is the simple concatenation of the boot sector and the kernel
+# It may be use in bochs or on a real floppy, but NOT in qemu (see below)
+sos_bsect.img: bsect.bin sos.bin
+ cat $^ > $@
+ @echo "You can use the $@ image in bochs or on a real floppy (NOT qemu)"
+
+# For qemu, the trick is to tell it we have *more* than 1440 sectors (720kB).
+# Rtherwise the qemu disk geometry will be configured to be that of a 720kB
+# floppy, while our boot sector assumes it to be 1.44MB
+sos_qemu.img: sos_bsect.img
+ # Padding with 0s after the bsect/kernel image
+ cat $< /dev/zero | dd of=$@ bs=1k count=1440
+ @echo "You can use the $@ image in qemu, bochs, or on a real floppy"
+
+# we extract the boot sector from the main ELF binary
+bsect.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -j .bootsect $< $@
+
+# we extract the kernel code from the main ELF binary
+sos.bin: sos_bsect.elf
+ $(OBJCOPY) -v -O binary -R .bootsect $< $@
+
+# The main ELF binary contains the boot sector and the kernel code
+# linked together (hence we deal with a SINGLE image that we split
+# above) because they share some symbol definitions
+sos_bsect.elf: bootsect.o compile_kernel
+ $(LD) --warn-common -T ./sos_bsect.lds -o $@ \
+ bootsect.o $(wildcard ../hwcore/*.o ../drivers/*.o ../sos/*.o)
+
+compile_kernel:
+ $(MAKE) -C ..
+
+clean:
+ $(RM) *.img *.elf *.bin *~ *.o *.out
diff --git a/sos-code-article4/extra/README b/sos-code-article4/extra/README
new file mode 100644
index 0000000..0272f1f
--- /dev/null
+++ b/sos-code-article4/extra/README
@@ -0,0 +1,73 @@
+
+Contents of the extra/ directory
+================================
+
+Data and configuration files to support generation of sos on non-x86
+and/or grub-less hosts:
+ - dot.mkvars: file to copy as .mkvars in the root directory to
+ compile on a non-x86 host, and to generate the grub floppy image on
+ a grub-less host
+ - grub.img.gz: compressed image of a Grub floppy (without any
+ kernel). Used by dot.mkvars.
+ - mtoolsrc: file needed by .mkvars to compile a the floppy image
+
+Support of a sos-specific boot sector:
+ - Makefile: rules to compile sos_bsect.img, the floppy image with the
+ boot sector and the Sos
+ - bootsect.S: x86 Sos boot sector (GNU as). Depends on sos_bsect.lds
+ - sos_bsect.lds: ld script to bind the boot sector with the remaining
+ of the kernel
+
+Misc:
+ - qemu-port-e9.diff: patch over qemu to support the bochs "port 0xe9 hack"
+
+
+What you can do with these files
+================================
+
+
+*** Compile SOS from another architecture:
+------------------------------------------
+ - compile a cross-compiler for the i586-gnu target. This involves
+ compiling the binutils and gcc. Here are example configuration
+ options for them:
+ binutils (replace sparc-cun-solaris with your arch):
+ ../binutils-2.13/configure --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/binutils-2.11 --host=sparc-sun-solaris2.7 i586-gnu
+ make && make install
+ gcc (ditto):
+ CFLAGS="-O2 -Dinhibit_libc" ../gcc-3.2/configure --target=i586-gnu --prefix=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/stow/gcc-3.2 --with-as=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/as --with-ld=/udd/ddecotig/temp_dd/xgcc/host-sparc-solaris7/bin/ld --with-gnu-as --with-gnu-ld --enable-languages=c --disable-shared --disable-multilib --disable-nls --enable-threads=single
+ make && make install
+ - compile the mtools
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS from an x86 where grub is not or incorrectly installed:
+--------------------------------------------------------------------------
+ - copy dot.mkvars to the root directory of SOS, as ".mkvars"
+ - customize the CC/LD/... variables to suit your cross-compiler
+ installatioon
+ - now you may run make from the SOS root directory, it should
+ generate the Grub boot floppy image. The following warning is
+ normal:
+ .mkvars:16: attention : écrasement des commandes pour la cible « grub-sos.img »
+ Makefile:92: attention : anciennes commandes ignorées pour la cible « grub-sos.img »
+
+
+*** To compile SOS with its own bootloader:
+-------------------------------------------
+ - for cross-architecture compilation: see above
+ - cd to this extra/ directory
+ - run 'make'
+ - the floppy image is: sos_bsect.img
+ NOTE : SOS will not boot correctly this way after article 2 !
+
+
+--
+David Decotigny
diff --git a/sos-code-article4/extra/bootsect.S b/sos-code-article4/extra/bootsect.S
new file mode 100644
index 0000000..f01ca20
--- /dev/null
+++ b/sos-code-article4/extra/bootsect.S
@@ -0,0 +1,393 @@
+
+/*
+ * @(#) $Id: bootsect.S,v 1.6 2004/06/18 07:43:51 d2 Exp $
+ * Description : Bootsecteur en syntaxe AT&T
+ * Auteurs : Thomas Petazzoni & Fabrice Gautier & Emmanuel Marty
+ * Jerome Petazzoni & Bernard Cassagne & coffeeman
+ * David Decotigny
+ * Bug reports to kos-misc@enix.org
+ */
+
+/*
+ * But global de ce bootsecteur :
+ *
+ * - Initialiser la becane
+ * - Charger le kernel
+ * - Passer en mode protege
+ * - Executer le kernel
+ *
+ * Taille restante : Je vous rappelle qu'un bootsecteur ne peut faire
+ * qu'au maximum 512 octets dont 2 octets obligatoires 0xAA55. Sur
+ * les 510 octets reellement utilisables, il reste 3 octets dispo (60
+ * si on decide d'enlever le BPB un jour) !!!
+ *
+ * thomas_petazzoni : - detection des codes d'erreurs de chargement
+ * David_Decotigny : - Passage en GNU as
+ * David_Decotigny : - Chargement du noyau au-dela du 1er Mega (taille
+ * max = 0x9e000 octets = 632ko), pour avoir le
+ * meme noyau sous grub et avec le bootsecteur
+ */
+
+ /*
+ * Sequence d'operations :
+ * - Le BIOS charge le bootsect en 0x7c00 (BOOT_ADRESS). On choisit
+ * la representation 0x7c0:0000 pour que le .org 0 reste valide
+ * - Le bootsect se deplace de lui-meme en 0x9f000 (COPY_ADRESS). On
+ * choisit la representation 0x9f00:0000 pour que le .org 0 reste
+ * valide
+ * - Le bootsect verifie que le processeur est du type 386+
+ * - Il charge le noyau depuis la disquette en memoire a partir de
+ * 0x1000 (LOAD_ADRESS). Le noyau peut au max tenir sur
+ * SECTORS_TO_LOAD secteurs
+ * - Il passe en pmode flat (apres ouverture a20)
+ * - Il recopie le noyau (situe en LOAD_ADRESS) vers son adresse
+ * finale (FINAL_ADDRESS = 2Mo). La recopie se fait sur tout l'espace
+ * LOAD_ADRESS ---> COPY_ADRESS, c'est a dire sur 0x9e000 octets =
+ * 632ko. Le noyau peut donc au max faire 632ko. Le nombre max de
+ * secteurs de disquette qu'on peut charger est donc 1264
+ */
+
+
+/* La taille de la pile */
+#define BOOT_STACK_SIZE 0x4000
+
+ .file "bootsect.S"
+
+ /* Tout est place dans une seule section */
+ .section ".bootsect"
+
+ /* L'essentiel du bootsector (sauf les 1eres instructions)
+ sont a un offset 0. On fait en sorte que le compilo soit
+ d'accord la-dessus. Quand on a des adresse realm exotiques
+ (0x7c00, 0x9f000, ...), on s'arrange toujours pour avoir un
+ offset de 0 => on choisira le segment adapte (0x7c0,
+ 0x9f00, ...). Il ne faut pas oublier le ld -Ttext 0 */
+ .org 0
+
+ /* Pour que gas genere du 16bits, afin que ca marche en realm */
+ .code16
+
+#define SECTORS_TO_LOAD 128 /* 64 ko */ /* MAX=1264 */
+
+/*
+ * Parametres de la disquette. Comme c'est chiant de faire une
+ * procedure de detection auto, et que ca prend de la place, on fait
+ * ca "a la main". Par exemple, une DD 720 Ko a 9 secteurs/piste, une
+ * 1.44 Mo a 18 secteurs/pistes
+ */
+#define CYLS 80
+#define HEADS 1
+#define SECTS 18
+
+#define BOOT_ADRESS 0x07C00 /* Adresse de demarrage (lineaire) */
+#define BOOT_SEG (BOOT_ADRESS>>4) /* Segment de Boot */
+#define BOOT_SIZE 512 /* Taille bu bootsecteur */
+#define COPY_ADRESS 0x9F000 /* La ou on va copier le
+ bootsecteur (lineaire) */
+#define COPY_SEG (COPY_ADRESS>>4) /* Segment de la ou on va
+ copier le bootsecteur */
+#define LOAD_ADRESS 0x01000 /* 1er chargement du systeme */
+#define LOAD_SEG (LOAD_ADRESS>>4) /* Segment du 1er chargement du */
+#define MAX_KERN_LEN COPY_ADRESS-LOAD_ADRESS /* Taille noyau maxi */
+
+/* IMPORTANT : Cette valeur DOIT etre identique a l'adresse presente
+ dans sos.lds ! */
+#define FINAL_ADDRESS 0x200000 /* Adresse finale (physique de 0 a 4G)
+ ou est charge le noyau */
+
+#define OP16 .byte 0x66 ;
+#define OP32 .byte 0x66 ;
+
+/*
+ * Procedure qui vide le buffer clavier.
+ */
+#define WAITKB \
+ 1: ;\
+ .word 0xeb ;\
+ .word 0xeb ;\
+ inb $0x64, %al ;\
+ andb $0x2, %al ;\
+ jnz 1b
+
+ /* Le point d'entree dans le bootsect */
+.globl _bsect
+_bsect:
+
+ /*
+ * La portion qui suit est situee a un offset 0x7c00 en
+ * memoire. Attention donc aux references memoire dans cette
+ * partie. On choisit de rester en offset 0 (.org 0), mais on
+ * charge correctement les segments a 0x7c0.
+ */
+
+ movw $BOOT_SEG, %ax /* le bootsecteur est a 0x7C00 en lineaire */
+ movw %ax, %ds /* on le copie a l'adresse COPY_ADRESS */
+ xorw %si, %si /* comme cette adresse est la plus haute de la mem */
+ xorw %di, %di /* on pourra charger un kernel + gros */
+ movw $(BOOT_SIZE>>1), %cx
+ movw $COPY_SEG, %ax
+ movw %ax, %es
+ cld
+ rep ; movsw
+
+ /* on continue a executer le bootsecteur, mais maintenant a
+ partir de 0x9F000, qu'on represente sous la forme
+ 0x9f00:offset */
+ ljmp $COPY_SEG, $here
+
+ /*
+ * A partir de maintenant, on est a un offset 0 en memoire
+ * (segment 0x9f00), conformement a ce que veut le compilo.
+ */
+here:
+ movw %ax, %ds
+
+ /* Petite pile temporaire (1k - 3.84k en RAM ; les adresses 0-1k
+ correspondent au vecteur d'interruptions). */
+ movw %ax, %ss
+ movw $(LOAD_ADRESS - 0x10), %sp
+
+ /* Efface l'ecran */
+ movb $0x0, %ah
+ movb $0x3, %al
+ int $0x10
+
+ /* Affiche les messages d'attente */
+ movw $loadkern, %si
+ call message
+ movw $check, %si
+ call message
+
+check386:
+ /*
+ * la attention, plus complexe : on teste si le proc est un
+ * 386+ pour cela, on va essayer de modifier les bits 12 ? 14
+ * du registre E-flag si la modification reste, alors le proc
+ * est un 386+, sinon, c'est =< 286
+ *
+ * Merci a Emmanuel Marty pour la compatibilite avec les 386
+ * "pre-jurassique"
+ */
+
+ pushf /* on sauvegarde le E-Flag */
+ movb $0x70, %ah
+ pushw %ax
+ popf
+ pushf
+ popw %ax
+ orb %ah, %ah
+ je no386 /* si la modif n'est pas valable, alors on saute a
+ no386 */
+ popf /* on les restaure ? la fin ... */
+
+ /* Message de confirmation de 386+ et d'attente */
+ movw $found386, %si
+ call message
+ movw $loading, %si
+ call message
+
+/* Copie du noyau disquette => RAM a partir de 0x1000
+ L'adresse de destination est définie par es:0, où es vaut
+ initialement 0x100 (ie correspond alors à l'adresse 256*16, soit 4
+ ko). Chaque itération incrémente ce registre es de 32, ce qui
+ correspond à un bond de 32*16 en mémoire, soit la taille d'un
+ secteur. De cette façon, puisqu'on joue sur les segments plutôt que
+ sur les offsets, la taille du noyau n'est pas limitée à 64 ko. Elle
+ est limitée par contre à la taille de la mémoire disponible sous
+ les 1Mo, \ie 640 ko (0x9f000 - 0x1000). */
+copyKernel:
+ /* Chargement du noyau en LOAD_SEG:0 */
+ /* 3 iterateurs :
+ - load_size : le nbre de secteurs a charger
+ - cl : le secteur ou on en est pour le
+ cylindre en cours (<= SECTS)
+ - dh : la tete en cours (0/1)
+ */
+ movb $0, %dl
+ movw $LOAD_SEG, %ax
+ movw %ax, %es
+
+ xorw %bx, %bx
+ xorw %dx, %dx
+ movw $1, %cx /* premier secteur */
+
+.nextsector: /* prochain secteur */
+ incb %cl /* en incrementant CL */
+ cmpb $SECTS, %cl /* si CL =< SECTS (=nbre de secteurs/pistes)
+ alors on charge */
+ jbe .sector
+ movb $1, %cl /* sinon on revient au secteur 1 */
+ incb %dh /* mais sur l'autre tete */
+ cmpb $1, %dh /* on recompare, si DH =< 1 */
+ je .sector /* on charge */
+ movb $0, %dh /* sinon on repasse a la tete 0 */
+ incb %ch /* mais on change de cylindre */
+
+.sector:
+ pushw %es
+ movw $0x0201, %ax /* service 0x2, chargement 0x1 seecteur */
+ int $0x13 /* Go ! */
+ jc halt /* erreur */
+ popw %ax
+ addw $32, %ax /* on a charge un secteur, donc on doit
+ charger 512 bytes plus loin */
+ movw %ax, %es /* on avance donc le segment du buffer de
+ 32bytes, ie 1 secteur en RAM (car 32*16=512) */
+
+ movw $(0x0E*256+'.'), %ax /* affiche un point */
+ int $0x10
+
+ decw (load_size) /* et on repart pour le prochain secteur
+ tant qu'on n'a pas fini ! */
+ jnz .nextsector
+
+after:
+ movw $0x03f2, %dx
+ inb %dx, %al /* stoppe le moteur */
+ andb $0x0f, %al
+ outb %al, %dx
+
+ cli /* on interdit les interruptions */
+
+fincopie:
+ pushw %cs
+ popw %ds
+
+ /* on ouvre la porte A20 */
+ WAITKB /* on vide le buffer */
+ movb $0xd1, %al /* on met a jour le port */
+ outb %al, $0x64
+ WAITKB
+ movb $0xdf, %al /* bit 2 = ouverture/fermeture */
+ outb %al, $0x60
+
+ /*
+ * init gdt
+ */
+InitGDT:
+ /* Préparation du flat mode */
+ lgdt gdtr
+
+GoPMode:
+ /* Passage en mode protégé */
+ movl %cr0, %eax
+ orb $1, %al /* set PE bit to 1 */
+ movl %eax, %cr0
+
+ /* we are not yet in Pmode jump 'in' pmode clearing prefetch
+ * queue and loading a new selector */
+ movw $0x10, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+/*
+ * Code 32 bits ============================================================
+ */
+ .code32
+
+JumpToHere32: /* Se deplace a l'endroit actuel, en passant en 32bits
+ et en utilisant la gdt, et vide la prefetch queue */
+ .byte 0x66 /* Prefixe 32bits : en realite, jusqu'au jmp, on est
+ encore en 16 bits */
+ ljmp $0x8, $(COPY_ADRESS+(Here32))
+Here32:
+ /* Et voila : On est en 32 bits vrai */
+
+MoveKernelToFinalAddr: /* Deplace le noyau (en LOAD_ADDRESS) vers sa
+ destination finale (FINAL_ADDRESS) */
+ movl $0x10, %eax
+ movl %eax, %ds /* Seg Src = DSeg */
+ movl %eax, %es /* Sed Dest = DSeg */
+ cld
+ movl $LOAD_ADRESS, %esi /* On commence la copie au debut du noyau */
+ movl $FINAL_ADDRESS, %edi /* On copie vers cette adresse */
+ movl $MAX_KERN_LEN, %ecx /* Taille recopie */
+ shrl $2, %ecx
+ rep
+ movsl
+
+LaunchKernel:
+ /* Met en place une pile au niveau du symbole "stack" */
+ movl %eax, %ss
+ movl $(stack + BOOT_STACK_SIZE), %ebp
+ movl %ebp, %esp
+
+ /* Saut vers le noyau. La GDT est en place (flat mode), les
+ * selecteurs aussi, a20 est ouverte, et les interruptions sont
+ * cli + pas de idt. Le PIC n'est pas programme */
+ ljmp $0x8, $sos_main
+
+/*
+ * Utilities ============================================================
+ */
+ .code16
+
+message:
+ lodsb /* charge ds:si dans al et incremente si */
+ orb %al, %al /* si al = 0 */
+ jz 1f
+ movb $0x0e, %ah /* service 0Eh (affichage d'un caractere) */
+ movw $0x0007, %bx /* Parametres : blanc sur fond noir */
+ int $0x10 /* Appel de l'interruption 10h */
+ jmp message /* On repart au début ... */
+ 1: ret /* si la chaine est finie alors on retourne
+ dans la fonction appelante */
+
+halt:
+ pushw %cs
+ popw %es
+ movw $haltmsg, %si
+ call message
+ cli
+ 1: jmp 1b
+ ret
+
+no386:
+ movw $need386, %si
+ call message
+ call halt
+
+ /*
+ * GDT
+ */
+
+gdt:
+gdtr:
+NULL_Desc:
+ .word (EndGDT)-(gdt)-1 /* Taille GDT */
+ .long (gdt)+COPY_ADRESS
+unused:
+ .word 0
+
+CS_Desc: /* 0x8 */
+ .word 0xFFFF, 0
+ .byte 0, 0x9B, 0xCF, 0
+
+DS_Desc: /* 0x10 */
+ .word 0xFFFF, 0
+ .byte 0, 0x93, 0xCF, 0
+
+EndGDT:
+
+ /* quelques messages */
+
+loadkern: .string "-= S O S =- : The Simple Operating System \r\n"
+check: .string "Checking for a 386+ processor... "
+found386: .string " [OK]\r\n"
+need386: .string " [FAILED]\r\n"
+diskerror: .string "Disk Error\r\n"
+loading: .string "Loading... "
+haltmsg: .string "System Halted\r\n"
+
+/*** Les code/données du boot secteur se terminent ICI. le marqueur de
+ * fin (aa55) est ajouté automatiquement par le script ld
+ * sos_bsect.lds ***/
+
+/* La pile de 16k qu'on utilise au niveau de LaunchKernel se trouve
+ declaree avec le noyau, dans sa section ".bss", cad HORS du boot
+ secteur ! (sinon ca depasserait 512B, forcément). On aurait pu la
+ définir directement dans le sos_bsect.lds, ou dans un fichier .c
+ auxiliaire pour plus de clarté */
+.comm stack, BOOT_STACK_SIZE
diff --git a/sos-code-article4/extra/dot.mkvars b/sos-code-article4/extra/dot.mkvars
new file mode 100644
index 0000000..1f7dca5
--- /dev/null
+++ b/sos-code-article4/extra/dot.mkvars
@@ -0,0 +1,29 @@
+# For cross-compilation and/or installations without grub available,
+# copy this file as .mkvars to the root directory of the SOS sources,
+# and customize the CC/LD/... variables. You still need the mtools
+# installed and running
+
+CC := i586-gnu-gcc
+LD := i586-gnu-ld
+OBJCOPY := i586-gnu-objcopy
+CFLAGS += -O3
+
+# Configuration of mtools
+MTOOLSRC = extra/mtoolsrc
+export MTOOLSRC
+
+$(MULTIBOOT_IMAGE): $(KERNEL_OBJ) menu.txt
+ gzip -dc < extra/grub.img.gz > $@
+ mcopy menu.txt v:/boot/grub/
+ mmd v:/system
+ mcopy sos.elf v:/system/sos.elf
+
+menu.txt:
+ echo timeout 0 > $@
+ echo default 0 >> $@
+ echo title SOS >> $@
+ echo "root (fd0)" >> $@
+ echo kernel /system/sos.elf >> $@
+
+runbochs: all
+ echo c | bochs -q
diff --git a/sos-code-article4/extra/grub.img.gz b/sos-code-article4/extra/grub.img.gz
new file mode 100644
index 0000000..4f98e74
--- /dev/null
+++ b/sos-code-article4/extra/grub.img.gz
Binary files differ
diff --git a/sos-code-article4/extra/mtoolsrc b/sos-code-article4/extra/mtoolsrc
new file mode 100644
index 0000000..df1a26e
--- /dev/null
+++ b/sos-code-article4/extra/mtoolsrc
@@ -0,0 +1,2 @@
+# For older versions of mtools, you may have to remove "filter"
+drive v: file="fd.img" 1.44M filter
diff --git a/sos-code-article4/extra/qemu-port-e9.diff b/sos-code-article4/extra/qemu-port-e9.diff
new file mode 100644
index 0000000..d8be044
--- /dev/null
+++ b/sos-code-article4/extra/qemu-port-e9.diff
@@ -0,0 +1,73 @@
+--- Makefile.target 17 Mar 2004 23:46:04 -0000 1.19
++++ Makefile.target 18 Mar 2004 14:20:29 -0000
+@@ -217,7 +217,8 @@
+ # must use static linking to avoid leaving stuff in virtual address space
+ VL_OBJS=vl.o osdep.o block.o monitor.o \
+ ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
+- fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
++ fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o \
++ port-e9.o
+ ifeq ($(TARGET_ARCH), ppc)
+ VL_OBJS+= hw.o
+ endif
+--- hw/pc.c 14 Mar 2004 21:46:48 -0000 1.2
++++ hw/pc.c 18 Mar 2004 14:20:29 -0000
+@@ -371,6 +371,7 @@
+ SB16_init();
+
+ fdctrl_init(6, 2, 0, 0x3f0, fd_table);
++ port_e9_init();
+
+ cmos_init(ram_size, boot_device);
+ }
+--- /dev/null 2003-01-30 11:24:37.000000000 +0100
++++ port-e9.c 2004-03-18 15:18:52.660493187 +0100
+@@ -0,0 +1,38 @@
++/*
++ * QEMU Port 0xe9 hack
++ *
++ * Copyright (c) 2000-2004 E. Marty, the bochs team, D. Decotigny
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++ * THE SOFTWARE.
++ */
++#include <stdio.h>
++#include <unistd.h>
++#include <inttypes.h>
++
++#include "vl.h"
++
++static void bochs_e9_write(void *opaque, uint32_t address, uint32_t data)
++{
++ write(fileno(stdout), &data, 1);
++}
++
++void port_e9_init ()
++{
++ register_ioport_write(0xe9, 1, 1, bochs_e9_write, NULL);
++}
+--- vl.h 17 Mar 2004 23:17:16 -0000 1.14
++++ vl.h 18 Mar 2004 14:29:06 -0000
+@@ -268,4 +268,7 @@
+ void term_flush(void);
+ void term_print_help(void);
+
++/* port-e9.c */
++void port_e9_init(void);
++
+ #endif /* VL_H */
diff --git a/sos-code-article4/extra/sos_bsect.lds b/sos-code-article4/extra/sos_bsect.lds
new file mode 100644
index 0000000..ac42f23
--- /dev/null
+++ b/sos-code-article4/extra/sos_bsect.lds
@@ -0,0 +1,61 @@
+/* Copyright (C) 2004, David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+SECTIONS
+{
+ /* ***********************************************
+ * The bootsector is here. We link it against the remaining of the kernel
+ * in order to automatically figure out its size that must be loaded
+ * from file to memory (see the load_size definition below)
+ */
+
+ /* If we use one, we put the boot sector here. We don't set its
+ * address to 0x7c000 (aka 0x7c00:0), since it reloads itself to
+ * 0x9f000, causing the 0x7c000 address to be meaningless too. So we
+ * chose to pretend that the address is 0x0, and to make a little
+ * address arithmetic in bootsect.S */
+ .bootsect 0x0 :
+ {
+ /* The code for the boot sector goes here */
+ *(.bootsect);
+
+ /* The load_size symbol contains the size of the area (in
+ * sectors, aka 512 Bytes) that the boot sector should copy from
+ * the disk. The bss section is not included since it uses 0
+ * bytes on disk */
+ load_size = .;
+ LONG((__e_load - __b_load + 511) >> 9);
+ /* ---> This is equivalent to ceil( (__e_load - __b_load) / 512 ) */
+
+ /* At offsets 511 and 512, we set the boot sector signature (AA55h) */
+ . = 0x1fe;
+ SHORT(0xAA55);
+ }
+}
+
+
+/* This is to avoid a cut/paste here. Please notice that a multiboot
+ * section WILL be inserted, which is NOT mandatory (we could have
+ * removed it without getting into trouble). Please note however that
+ * the *.bin files will NOT be multiboot compatible (they are not in ELF
+ * format): they are expected to be directly booted by the BIOS (or
+ * by the "chainloader" command of Grub). */
+INCLUDE ../support/sos.lds
+
+/* We overload the entry set in sos.lds, just to avoid an ld warning */
+ENTRY(sos_main);
diff --git a/sos-code-article4/hwcore/exception.c b/sos-code-article4/hwcore/exception.c
new file mode 100644
index 0000000..9ab5aff
--- /dev/null
+++ b/sos-code-article4/hwcore/exception.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "idt.h"
+#include "irq.h"
+
+#include "exception.h"
+
+/* array of exception wrappers, defined in exception_wrappers.S */
+extern sos_vaddr_t sos_exception_wrapper_array[SOS_EXCEPT_NUM];
+
+/* arrays of exception handlers, shared with exception_wrappers.S */
+sos_exception_handler_t sos_exception_handler_array[SOS_EXCEPT_NUM] =
+ { NULL, };
+
+sos_ret_t sos_exceptions_setup(void)
+{
+ /* We inidicate that the double fault exception handler is defined,
+ and give its address. this handler is a do-nothing handler (see
+ exception_wrappers.S), and it can NOT be overriden by the
+ functions below */
+ return sos_idt_set_handler(SOS_EXCEPT_BASE + SOS_EXCEPT_DOUBLE_FAULT,
+ (sos_vaddr_t) sos_exception_wrapper_array[SOS_EXCEPT_DOUBLE_FAULT],
+ 0 /* CPL0 routine */);
+}
+
+
+sos_ret_t sos_exception_set_routine(int exception_number,
+ sos_exception_handler_t routine)
+{
+ sos_ret_t retval;
+ sos_ui32_t flags;
+
+ if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM))
+ return -SOS_EINVAL;
+
+ /* Double fault not supported */
+ if (exception_number == SOS_EXCEPT_DOUBLE_FAULT)
+ return -SOS_ENOSUP;
+
+ sos_disable_IRQs(flags);
+
+ retval = SOS_OK;
+
+ /* Set the exception routine to be called by the exception wrapper */
+ sos_exception_handler_array[exception_number] = routine;
+
+ /* If the exception is to be enabled, update the IDT with the exception
+ wrapper */
+ if (routine != NULL)
+ retval
+ = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number,
+ (sos_vaddr_t) sos_exception_wrapper_array[exception_number],
+ 0 /* CPL0 routine */);
+ else /* Disable the IDT entry */
+ retval
+ = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number,
+ (sos_vaddr_t)NULL /* No routine => disable IDTE */,
+ 0 /* don't care */);
+
+ sos_restore_IRQs(flags);
+ return retval;
+}
+
+
+sos_exception_handler_t sos_exception_get_routine(int exception_number)
+{
+ if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM))
+ return NULL;
+
+ /* Double fault not supported */
+ if (exception_number == SOS_EXCEPT_DOUBLE_FAULT)
+ return NULL;
+
+ /* Expected to be atomic */
+ return sos_exception_handler_array[exception_number];
+}
diff --git a/sos-code-article4/hwcore/exception.h b/sos-code-article4/hwcore/exception.h
new file mode 100644
index 0000000..7e52fe5
--- /dev/null
+++ b/sos-code-article4/hwcore/exception.h
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWEXCEPT_H_
+#define _SOS_HWEXCEPT_H_
+
+/**
+ * @file exception.c
+ *
+ * Hardware exception routines management.
+ */
+
+#ifndef ASM_SOURCE
+# include <sos/errno.h>
+#endif
+
+/**
+ * Standard Intel x86 exceptions.
+ *
+ * @see Intel x86 doc vol 3, section 5.12.
+ */
+#define SOS_EXCEPT_DIVIDE_ERROR 0 // No error code
+#define SOS_EXCEPT_DEBUG 1 // No error code
+#define SOS_EXCEPT_NMI_INTERRUPT 2 // No error code
+#define SOS_EXCEPT_BREAKPOINT 3 // No error code
+#define SOS_EXCEPT_OVERFLOW 4 // No error code
+#define SOS_EXCEPT_BOUND_RANGE_EXCEDEED 5 // No error code
+#define SOS_EXCEPT_INVALID_OPCODE 6 // No error code
+#define SOS_EXCEPT_DEVICE_NOT_AVAILABLE 7 // No error code
+#define SOS_EXCEPT_DOUBLE_FAULT 8 // Yes (Zero)
+#define SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN 9 // No error code
+#define SOS_EXCEPT_INVALID_TSS 10 // Yes
+#define SOS_EXCEPT_SEGMENT_NOT_PRESENT 11 // Yes
+#define SOS_EXCEPT_STACK_SEGMENT_FAULT 12 // Yes
+#define SOS_EXCEPT_GENERAL_PROTECTION 13 // Yes
+#define SOS_EXCEPT_PAGE_FAULT 14 // Yes
+#define SOS_EXCEPT_INTEL_RESERVED_1 15 // No
+#define SOS_EXCEPT_FLOATING_POINT_ERROR 16 // No
+#define SOS_EXCEPT_ALIGNEMENT_CHECK 17 // Yes (Zero)
+#define SOS_EXCEPT_MACHINE_CHECK 18 // No
+#define SOS_EXCEPT_INTEL_RESERVED_2 19 // No
+#define SOS_EXCEPT_INTEL_RESERVED_3 20 // No
+#define SOS_EXCEPT_INTEL_RESERVED_4 21 // No
+#define SOS_EXCEPT_INTEL_RESERVED_5 22 // No
+#define SOS_EXCEPT_INTEL_RESERVED_6 23 // No
+#define SOS_EXCEPT_INTEL_RESERVED_7 24 // No
+#define SOS_EXCEPT_INTEL_RESERVED_8 25 // No
+#define SOS_EXCEPT_INTEL_RESERVED_9 26 // No
+#define SOS_EXCEPT_INTEL_RESERVED_10 27 // No
+#define SOS_EXCEPT_INTEL_RESERVED_11 28 // No
+#define SOS_EXCEPT_INTEL_RESERVED_12 29 // No
+#define SOS_EXCEPT_INTEL_RESERVED_13 30 // No
+#define SOS_EXCEPT_INTEL_RESERVED_14 31 // No
+
+#ifndef ASM_SOURCE
+
+typedef void (*sos_exception_handler_t)(int exception_number);
+
+sos_ret_t sos_exceptions_setup(void);
+sos_ret_t sos_exception_set_routine(int exception_number,
+ sos_exception_handler_t routine);
+sos_exception_handler_t sos_exception_get_routine(int exception_number);
+#endif /* ! ASM_SOURCE */
+
+#endif /* _SOS_HWEXCEPT_H_ */
diff --git a/sos-code-article4/hwcore/exception_wrappers.S b/sos-code-article4/hwcore/exception_wrappers.S
new file mode 100644
index 0000000..2f7665c
--- /dev/null
+++ b/sos-code-article4/hwcore/exception_wrappers.S
@@ -0,0 +1,197 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "exception.h"
+
+.file "exception_wrappers.S"
+
+.text
+
+/* The address of the table of handlers (defined in exception.c) */
+.extern sos_exception_handler_array
+
+/* The address of the table of wrappers (defined below, and shared
+ with exception.c */
+.globl sos_exception_wrapper_array
+
+
+/**
+ * For exceptions with/without error code, refer to Intel x86 doc vol 3,
+ * section 5.12
+ */
+
+/* These wrappers are for exceptions without error code */
+.irp id, \
+ SOS_EXCEPT_DIVIDE_ERROR, \
+ SOS_EXCEPT_DEBUG, \
+ SOS_EXCEPT_NMI_INTERRUPT, \
+ SOS_EXCEPT_BREAKPOINT, \
+ SOS_EXCEPT_OVERFLOW, \
+ SOS_EXCEPT_BOUND_RANGE_EXCEDEED, \
+ SOS_EXCEPT_INVALID_OPCODE, \
+ SOS_EXCEPT_DEVICE_NOT_AVAILABLE, \
+ SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN, \
+ SOS_EXCEPT_INTEL_RESERVED_1, \
+ SOS_EXCEPT_FLOATING_POINT_ERROR, \
+ SOS_EXCEPT_MACHINE_CHECK, \
+ SOS_EXCEPT_INTEL_RESERVED_2, \
+ SOS_EXCEPT_INTEL_RESERVED_3, \
+ SOS_EXCEPT_INTEL_RESERVED_4, \
+ SOS_EXCEPT_INTEL_RESERVED_5, \
+ SOS_EXCEPT_INTEL_RESERVED_6, \
+ SOS_EXCEPT_INTEL_RESERVED_7, \
+ SOS_EXCEPT_INTEL_RESERVED_8, \
+ SOS_EXCEPT_INTEL_RESERVED_9, \
+ SOS_EXCEPT_INTEL_RESERVED_10, \
+ SOS_EXCEPT_INTEL_RESERVED_11, \
+ SOS_EXCEPT_INTEL_RESERVED_12, \
+ SOS_EXCEPT_INTEL_RESERVED_13, \
+ SOS_EXCEPT_INTEL_RESERVED_14
+
+ .p2align 2, 0x90
+ sos_exception_wrapper_\id:
+ .type sos_exception_wrapper_\id,@function
+
+ /* Fake error code */
+ pushl $0
+ /* Backup the context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Call the handler with exception number as
+ * argument */
+ pushl $\id
+ leal sos_exception_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+
+ popl %ebp
+ /* Remove fake error code */
+ addl $4, %esp
+ iret
+.endr
+
+ /* These wrappers are for exceptions with error code */
+.irp id, \
+ SOS_EXCEPT_INVALID_TSS, \
+ SOS_EXCEPT_SEGMENT_NOT_PRESENT, \
+ SOS_EXCEPT_STACK_SEGMENT_FAULT, \
+ SOS_EXCEPT_GENERAL_PROTECTION, \
+ SOS_EXCEPT_PAGE_FAULT, \
+ SOS_EXCEPT_ALIGNEMENT_CHECK
+
+ .p2align 2, 0x90
+ sos_exception_wrapper_\id:
+ .type sos_exception_wrapper_\id,@function
+
+ /* ret eflags */
+ /* ret cs */
+ /* ret eip */
+ /* Error code */
+
+ /* Backup the context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Call the handler with exception number as
+ * argument */
+ pushl $\id
+ leal sos_exception_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Error code isn't compatible with iretd */
+ addl $4, %esp
+
+ iret
+.endr
+
+
+/* Double fault handler not supported. We must define it since we
+ define an entry for it in the sos_exception_wrapper_array. */
+.irp id, SOS_EXCEPT_DOUBLE_FAULT
+.p2align 2, 0x90
+sos_exception_wrapper_\id:
+.type sos_exception_wrapper_\id,@function
+1: hlt
+ jmp 1b /* Machine halting */
+.endr
+
+/* Build the sos_irq_wrapper_array, shared with interrupt.c */
+.section ".rodata"
+.p2align 5, 0x0
+sos_exception_wrapper_array:
+ .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
+ 16,17,18,19,20,21,22,23,24,25,26,27,29,30,31
+ .long (sos_exception_wrapper_\id)
+ .endr
diff --git a/sos-code-article4/hwcore/gdt.c b/sos-code-article4/hwcore/gdt.c
new file mode 100644
index 0000000..7945c8c
--- /dev/null
+++ b/sos-code-article4/hwcore/gdt.c
@@ -0,0 +1,150 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "segment.h"
+
+#include "gdt.h"
+
+
+/**
+ * The sructure of a segment descriptor.
+ *
+ * @see Intel x86 doc, Vol 3, section 3.4.3, figure 3-8. For segment
+ * types, see section 3.5
+ */
+struct x86_segment_descriptor
+{
+ /* Lowest dword */
+ sos_ui16_t limit_15_0; /* Segment limit, bits 15..0 */
+ sos_ui16_t base_paged_addr_15_0; /* Base address, bits 15..0 */
+
+ /* Highest dword */
+ sos_ui8_t base_paged_addr_23_16; /* Base address bits 23..16 */
+ sos_ui8_t segment_type:4; /* Section 3.4.3.1 (code/data)
+ and 3.5 (system) of Intel x86 vol 3 */
+ sos_ui8_t descriptor_type:1; /* 0=system, 1=Code/Data */
+ sos_ui8_t dpl:2;
+ sos_ui8_t present:1;
+
+ sos_ui8_t limit_19_16:4; /* Segment limit, bits 19..16 */
+ sos_ui8_t custom:1;
+ sos_ui8_t zero:1;
+ sos_ui8_t op_size:1; /* 0=16bits instructions, 1=32bits */
+ sos_ui8_t granularity:1; /* 0=limit in bytes, 1=limit in pages */
+
+ sos_ui8_t base_paged_addr_31_24; /* Base address bits 31..24 */
+} __attribute__ ((packed, aligned (8)));
+
+
+/**
+ * The GDT register, which stores the address and size of the
+ * GDT.
+ *
+ * @see Intel x86 doc vol 3, section 2.4, figure 2-4; and section
+ * 3.5.1
+ */
+struct x86_gdt_register {
+ /* The maximum GDT offset allowed to access an entry in the GDT */
+ sos_ui16_t limit;
+
+ /* This is not exactly a "virtual" address, ie an adddress such as
+ those of instructions and data; this is a "linear" address, ie an
+ address in the paged memory. However, in SOS we configure the
+ segmented memory as a "flat" space: the 0-4GB segment-based (ie
+ "virtual") addresses directly map to the 0-4GB paged memory (ie
+ "linear"), so that the "linear" addresses are numerically equal
+ to the "virtual" addresses: this base_addr will thus be the same
+ as the address of the gdt array */
+ sos_ui32_t base_addr;
+} __attribute__((packed, aligned(8)));
+
+
+/**
+ * Helper macro that builds a Segment descriptor for the virtual
+ * 0..4GB addresses to be mapped to the linear 0..4GB linear
+ * addresses.
+ */
+#define BUILD_GDTE(descr_privilege_level,is_code) \
+ ((struct x86_segment_descriptor) { \
+ .limit_15_0= 0xffff, \
+ .base_paged_addr_15_0= 0, \
+ .base_paged_addr_23_16= 0, \
+ .segment_type= ((is_code)?0xb:0x3), \
+ /* With descriptor_type (below) = 1 (code/data), \
+ * see Figure 3-1 of section 3.4.3.1 in Intel \
+ * x86 vol 3: \
+ * - Code (bit 3 = 1): \
+ * bit 0: 1=Accessed \
+ * bit 1: 1=Readable \
+ * bit 2: 0=Non-Conforming \
+ * - Data (bit 3 = 0): \
+ * bit 0: 1=Accessed \
+ * bit 1: 1=Writable \
+ * bit 2: 0=Expand up (stack-related) \
+ * For Conforming/non conforming segments, see \
+ * Intel x86 Vol 3 section 4.8.1.1 \
+ */ \
+ .descriptor_type= 1, /* 1=Code/Data */ \
+ .dpl= ((descr_privilege_level) & 0x3), \
+ .present= 1, \
+ .limit_19_16= 0xf, \
+ .custom= 0, \
+ .op_size= 1, /* 32 bits instr/data */ \
+ .granularity= 1 /* limit is in 4kB Pages */ \
+ })
+
+
+/** The actual GDT */
+static struct x86_segment_descriptor gdt[] = {
+ [SOS_SEG_NULL] = (struct x86_segment_descriptor){ 0, },
+ [SOS_SEG_KCODE] = BUILD_GDTE(0, 1),
+ [SOS_SEG_KDATA] = BUILD_GDTE(0, 0),
+};
+
+sos_ret_t sos_gdt_setup(void)
+{
+ struct x86_gdt_register gdtr;
+
+ /* Address of the GDT */
+ gdtr.base_addr = (sos_ui32_t) gdt;
+
+ /* The limit is the maximum offset in bytes from the base address of
+ the GDT */
+ gdtr.limit = sizeof(gdt) - 1;
+
+ /* Commit the GDT into the CPU, and update the segment
+ registers. The CS register may only be updated with a long jump
+ to an absolute address in the given segment (see Intel x86 doc
+ vol 3, section 4.8.1). */
+ asm volatile ("lgdt %0 \n\
+ ljmp %1,$1f \n\
+ 1: \n\
+ movw %2, %%ax \n\
+ movw %%ax, %%ss \n\
+ movw %%ax, %%ds \n\
+ movw %%ax, %%es \n\
+ movw %%ax, %%fs \n\
+ movw %%ax, %%gs"
+ :
+ :"m"(gdtr),
+ "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE)),
+ "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA))
+ :"memory","eax");
+
+ return SOS_OK;
+}
diff --git a/sos-code-article4/hwcore/gdt.h b/sos-code-article4/hwcore/gdt.h
new file mode 100644
index 0000000..b7e3f4c
--- /dev/null
+++ b/sos-code-article4/hwcore/gdt.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_GDT_H_
+#define _SOS_GDT_H_
+
+/**
+ * @file gdt.h
+ *
+ * The routines that manage the GDT, the table that maps the virtual
+ * addresses (data/instructions, segment-relative), to "linear"
+ * addresses (ie paged-memory). In SOS/x86, we use a "flat" virtual
+ * space, ie the virtual and linear spaces are equivalent.
+ *
+ * @see Intel x86 doc vol 3, chapter 3
+ */
+
+#include <sos/errno.h>
+
+/**
+ * Configure the virtual space as a direct mapping to the linear
+ * address space (ie "flat" virtual space).
+ */
+sos_ret_t sos_gdt_setup(void);
+
+#endif /* _SOS_GDT_H_ */
diff --git a/sos-code-article4/hwcore/i8254.c b/sos-code-article4/hwcore/i8254.c
new file mode 100644
index 0000000..5fbb156
--- /dev/null
+++ b/sos-code-article4/hwcore/i8254.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <hwcore/ioports.h>
+
+#include "i8254.h"
+
+/** 82c54 clock frequency */
+#define I8254_MAX_FREQ 1193180
+
+/* Ports to communicate with the 82c54 */
+#define I8254_TIMER0 0x40
+#define I8254_TIMER1 0x41
+#define I8254_TIMER2 0x42
+#define I8254_CONTROL 0x43
+
+/**
+ * Configure the first timer of the 82c54 chip as a rate generator,
+ * which will raise an IRQ0 on a regular periodic basis, as given by
+ * the freq parameter. Second (RAM refresh) and third (speaker) timers
+ * are left unchanged. Maximum frequency is that of the 8254 clock, ie
+ * 1193180 Hz.
+ *
+ * Ahhh PC systems are nice toys: this maximum "strange" frequency
+ * equals that of the NTSC clock (14.31818 MHz) divided by 12. In
+ * turn, the famous 4.77 MHz cpu clock frequency of the first IBM PC
+ * is this same NTSC frequency divided by 3. Why the NTSC frequency as
+ * a base "standard" ? Because the 14.31818 MHz quartz were cheap at
+ * that time, and because it allows to simply drive altogether the
+ * cpu, the "time of day" timer, and the video signal generators.
+ */
+sos_ret_t sos_i8254_set_frequency(unsigned int freq)
+{
+ unsigned int nb_tick;
+
+ if (freq <= 0)
+ return -SOS_EINVAL;
+
+ /* Compute counter value */
+ nb_tick = I8254_MAX_FREQ / freq;
+
+ /* Counter must be between 1 and 65536 */
+ if (nb_tick > 65536)
+ return -SOS_EINVAL;
+ if (nb_tick <= 0)
+ return -SOS_EINVAL;
+
+ /* The i8254 interprets 0 to mean counter == 65536, because 65536
+ cannot be coded on 16bits */
+ if (nb_tick == 65536)
+ nb_tick = 0;
+
+ /* We want to configure timer0, we want to send both LSB+MSB to set
+ timer0 freq (-> 0x30), and we configure timer0 in mode 2, ie as a
+ rate generator (-> 0x4) ==> 0x34 */
+ outb(0x34, I8254_CONTROL);
+
+ /* Send LSB of counter first */
+ outb((nb_tick & 0xFF), I8254_TIMER0);
+
+ /* Send MSB of counter */
+ outb((nb_tick >> 8) & 0xFF, I8254_TIMER0);
+
+ return SOS_OK;
+}
diff --git a/sos-code-article4/hwcore/i8254.h b/sos-code-article4/hwcore/i8254.h
new file mode 100644
index 0000000..4838ff4
--- /dev/null
+++ b/sos-code-article4/hwcore/i8254.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_i8259_H_
+#define _SOS_i8259_H_
+
+#include <sos/errno.h>
+
+/**
+ * @file i8254.h PC programmable timer
+ *
+ * Programmable timer routines. See the Intel 82C54 datasheet (on kos
+ * website).
+ *
+ * @see i82C54 datasheet on Kos website.
+ */
+
+/** Change timer interrupt (IRQ 0) frequency */
+sos_ret_t sos_i8254_set_frequency(unsigned int freq);
+
+#endif /* _SOS_i8259_H_ */
diff --git a/sos-code-article4/hwcore/i8259.c b/sos-code-article4/hwcore/i8259.c
new file mode 100644
index 0000000..8391c07
--- /dev/null
+++ b/sos-code-article4/hwcore/i8259.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "ioports.h"
+
+#include "i8259.h"
+
+#define PIC_MASTER 0x20
+#define PIC_SLAVE 0xa0
+
+/** Setup the 8259 PIC */
+sos_ret_t sos_i8259_setup(void)
+{
+ /* Send ICW1: 8086 mode + NOT Single ctrl + call address
+ interval=8 */
+ outb(0x11, PIC_MASTER);
+ outb(0x11, PIC_SLAVE);
+
+ /* Send ICW2: ctrl base address */
+ outb(0x20, PIC_MASTER+1);
+ outb(0x28, PIC_SLAVE+1);
+
+ /* Send ICW3 master: mask where slaves are connected */
+ outb(0x4, PIC_MASTER+1);
+ /* Send ICW3 slave: index where the slave is connected on master */
+ outb(0x2, PIC_SLAVE+1);
+
+ /* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */
+ outb(0x1, PIC_MASTER+1);
+ outb(0x1, PIC_SLAVE+1);
+
+ /* Send OCW1:
+ * Closing all IRQs : waiting for a correct handler The only IRQ
+ * enabled is the cascade (that's why we use 0xFB for the master) */
+ outb(0xFB, PIC_MASTER+1);
+ outb(0xFF, PIC_SLAVE+1);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_i8259_enable_irq_line(int numirq)
+{
+ if(numirq < 8)
+ /* irq on master PIC */
+ outb((inb(PIC_MASTER+1) & ~(1 << numirq)), PIC_MASTER+1);
+ else
+ /* irq on slave PIC */
+ outb((inb(PIC_SLAVE+1) & ~(1 << (numirq-8))), PIC_SLAVE+1);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_i8259_disable_irq_line(int numirq)
+{
+ if(numirq < 8)
+ /* irq on master PIC */
+ outb((inb(PIC_MASTER+1) | (1 << numirq)), PIC_MASTER+1);
+ else
+ /* irq on slave PIC */
+ outb((inb(PIC_SLAVE+1) | (1 << (numirq-8))), PIC_SLAVE+1);
+
+ return SOS_OK;
+}
diff --git a/sos-code-article4/hwcore/i8259.h b/sos-code-article4/hwcore/i8259.h
new file mode 100644
index 0000000..c1771dd
--- /dev/null
+++ b/sos-code-article4/hwcore/i8259.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_i8259_H_
+#define _SOS_i8259_H_
+
+#include <sos/errno.h>
+
+/**
+ * @file i8259.h PIC
+ *
+ * PIC Management routines. See the Intel 8259A datasheet (on kos
+ * website), page 9+. Should be not be used directly: only interrupt.c
+ * should use this.
+ *
+ * @see i8259A datasheet on Kos website.
+ */
+
+/** Setup PIC and Disable all IRQ lines */
+sos_ret_t sos_i8259_setup(void);
+
+sos_ret_t sos_i8259_enable_irq_line(int numirq);
+
+sos_ret_t sos_i8259_disable_irq_line(int numirq);
+
+#endif /* _SOS_i8259_H_ */
diff --git a/sos-code-article4/hwcore/idt.c b/sos-code-article4/hwcore/idt.c
new file mode 100644
index 0000000..51e3a9d
--- /dev/null
+++ b/sos-code-article4/hwcore/idt.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "segment.h"
+
+#include "idt.h"
+
+/**
+ * An entry in the IDT, or "IDTE" in the following, ie a reference to
+ * a interrupt/trap routine or a task gate to handle the sw/hw
+ * interrupts and exceptions.
+ *
+ * @see figure 5-2, intel x86 doc, vol 3
+ */
+struct x86_idt_entry
+{
+ /* Low dword */
+ sos_ui16_t offset_low; /* 15..0, offset of the routine in the segment */
+ sos_ui16_t seg_sel; /* 31..16, the ID of the segment */
+
+ /* High dword */
+ sos_ui8_t reserved:5; /* 4..0 */
+ sos_ui8_t flags:3; /* 7..5 */
+ sos_ui8_t type:3; /* 10..8 (interrupt gate, trap gate...) */
+ sos_ui8_t op_size:1; /* 11 (0=16bits instructions, 1=32bits instr.) */
+ sos_ui8_t zero:1; /* 12 */
+ sos_ui8_t dpl:2; /* 14..13 */
+ sos_ui8_t present:1; /* 15 */
+ sos_ui16_t offset_high; /* 31..16 */
+} __attribute__((packed));
+
+
+/**
+ * The IDT register, which stores the address and size of the
+ * IDT.
+ *
+ * @see Intel x86 doc vol 3, section 2.4, figure 2-4
+ */
+struct x86_idt_register
+{
+ /* The maximum GDT offset allowed to access an entry in the GDT */
+ sos_ui16_t limit;
+
+ /* This is not exactly a "virtual" address, ie an adddress such as
+ those of instructions and data; this is a "linear" address, ie an
+ address in the paged memory. However, in SOS we configure the
+ segmented memory as a "flat" space: the 0-4GB segment-based (ie
+ "virtual") addresses directly map to the 0-4GB paged memory (ie
+ "linear"), so that the "linear" addresses are numerically equal
+ to the "virtual" addresses: this base_addr will thus be the same
+ as the address of the gdt array */
+ sos_ui32_t base_addr;
+} __attribute__((packed, aligned (8)));
+
+
+static struct x86_idt_entry idt[SOS_IDTE_NUM];
+
+sos_ret_t sos_idt_setup()
+{
+ struct x86_idt_register idtr;
+ int i;
+
+ for (i = 0 ;
+ i < SOS_IDTE_NUM ;
+ i++)
+ {
+ struct x86_idt_entry *idte = idt + i;
+
+ /* Setup an empty IDTE interrupt gate, see figure 5-2 in Intel
+ x86 doc, vol 3 */
+ idte->seg_sel = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE);
+ idte->reserved = 0;
+ idte->flags = 0;
+ idte->type = 0x6; /* Interrupt gate (110b) */
+ idte->op_size = 1; /* 32bits instructions */
+ idte->zero = 0;
+
+ /* Disable this IDT entry for the moment */
+ sos_idt_set_handler(i, (sos_vaddr_t)NULL, 0/* Don't care */);
+ }
+
+ /*
+ * Setup the IDT register, see Intel x86 doc vol 3, section 5.8.
+ */
+
+ /* Address of the IDT */
+ idtr.base_addr = (sos_ui32_t) idt;
+
+ /* The limit is the maximum offset in bytes from the base address of
+ the IDT */
+ idtr.limit = sizeof(idt) - 1;
+
+ /* Commit the IDT into the CPU */
+ asm volatile ("lidt %0\n"::"m"(idtr):"memory");
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_idt_set_handler(int index,
+ sos_vaddr_t handler_address,
+ int lowest_priviledge /* 0..3 */)
+{
+ struct x86_idt_entry *idte;
+
+ if ((index < 0) || (index >= SOS_IDTE_NUM))
+ return -SOS_EINVAL;
+ if ((lowest_priviledge < 0) || (lowest_priviledge > 3))
+ return -SOS_EINVAL;
+
+ idte = idt + index;
+ if (handler_address != (sos_vaddr_t)NULL)
+ {
+ idte->offset_low = handler_address & 0xffff;
+ idte->offset_high = (handler_address >> 16) & 0xffff;
+ idte->dpl = lowest_priviledge;
+ idte->present = 1; /* Yes, there is a handler */
+ }
+ else /* Disable this IDT entry */
+ {
+ idte->offset_low = 0;
+ idte->offset_high = 0;
+ idte->dpl = 0;
+ idte->present = 0; /* No, there is no handler */
+ }
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_idt_get_handler(int index,
+ sos_vaddr_t *handler_address,
+ int *lowest_priviledge)
+{
+ if ((index < 0) || (index >= SOS_IDTE_NUM))
+ return -SOS_EINVAL;
+
+ if (handler_address != NULL)
+ *handler_address = idt[index].offset_low
+ | (idt[index].offset_high << 16);
+ if (lowest_priviledge != NULL)
+ *lowest_priviledge = idt[index].dpl;
+
+ return SOS_OK;
+}
diff --git a/sos-code-article4/hwcore/idt.h b/sos-code-article4/hwcore/idt.h
new file mode 100644
index 0000000..7afe364
--- /dev/null
+++ b/sos-code-article4/hwcore/idt.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_IDT_H_
+#define _SOS_IDT_H_
+
+/**
+ * @file idt.h
+ *
+ * Manage the x86 Interrupt Descriptor Table, the table which maps the
+ * hardware interrupt lines, hardware exceptions, and software
+ * interrupts, to software routines. We only define "interrupt gate"
+ * IDT entries. Don't use it directly; refer instead to interrupt.c,
+ * exceptions.c and syscall.c.
+ *
+ * @see Intel x86 doc, Vol 3, chapter 5
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+
+/* Mapping of the CPU exceptions in the IDT (imposed by Intel
+ standards) */
+#define SOS_EXCEPT_BASE 0
+#define SOS_EXCEPT_NUM 32
+#define SOS_EXCEPT_MAX (SOS_HWEXCEPT_BASE + SOS_HWEXCEPT_NUM - 1)
+
+/* Mapping of the IRQ lines in the IDT */
+#define SOS_IRQ_BASE 32
+#define SOS_IRQ_NUM 16
+#define SOS_IRQ_MAX (SOS_IRQ_BASE + SOS_IRQ_NUM - 1)
+
+/**
+ * Number of IDT entries.
+ *
+ * @note Must be large enough to map the hw interrupts, the exceptions
+ * (=> total is 48 entries), and the syscall(s). Since our syscall
+ * will be 0x42, it must be >= 0x43. Intel doc limits this to 256
+ * entries, we use this limit.
+ */
+#define SOS_IDTE_NUM 256 /* 0x100 */
+
+/** Initialization routine: all the IDT entries (or "IDTE") are marked
+ "not present". */
+sos_ret_t sos_idt_setup(void);
+
+/**
+ * Enable the IDT entry if handler_address != NULL, with the given
+ * lowest_priviledge.\ Disable the IDT entry when handler_address ==
+ * NULL (the lowest_priviledge parameter is then ignored). Intel doc
+ * says that there must not be more than 256 entries.
+ *
+ * @note IRQ Unsafe
+ */
+sos_ret_t sos_idt_set_handler(int index,
+ sos_vaddr_t handler_address,
+ int lowest_priviledge /* 0..3 */);
+
+
+/**
+ * @note IRQ Unsafe
+ *
+ * @return the handler address and DPL in the 2nd and 3rd
+ * parameters
+ */
+sos_ret_t sos_idt_get_handler(int index,
+ sos_vaddr_t *handler_address,
+ int *lowest_priviledge);
+
+#endif /* _SOS_IDT_H_ */
diff --git a/sos-code-article4/hwcore/ioports.h b/sos-code-article4/hwcore/ioports.h
new file mode 100644
index 0000000..443acb7
--- /dev/null
+++ b/sos-code-article4/hwcore/ioports.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2004 All GPL'ed OS
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_IOPORTS_H_
+#define _SOS_IOPORTS_H_
+
+/**
+ * @ioports.h
+ *
+ * Intel-specific I/O space access routines.
+ */
+
+/* This macro allows to write to an I/O port */
+#define outb(value, port) \
+ __asm__ volatile ( \
+ "outb %b0,%w1" \
+ ::"a" (value),"Nd" (port) \
+ ) \
+
+// read one byte from port
+#define inb(port) \
+({ \
+ unsigned char _v; \
+ __asm__ volatile ( \
+ "inb %w1,%0" \
+ :"=a" (_v) \
+ :"Nd" (port) \
+ ); \
+ _v; \
+})
+
+#endif /* _SOS_IOPORTS_H_ */
diff --git a/sos-code-article4/hwcore/irq.c b/sos-code-article4/hwcore/irq.c
new file mode 100644
index 0000000..6ec3371
--- /dev/null
+++ b/sos-code-article4/hwcore/irq.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "idt.h"
+#include "i8259.h"
+
+#include "irq.h"
+
+/* array of IRQ wrappers, defined in irq_wrappers.S */
+extern sos_vaddr_t sos_irq_wrapper_array[SOS_IRQ_NUM];
+
+/* arrays of IRQ handlers, shared with irq_wrappers.S */
+sos_irq_handler_t sos_irq_handler_array[SOS_IRQ_NUM] = { NULL, };
+
+
+sos_ret_t sos_irq_setup(void)
+{
+ return sos_i8259_setup();
+}
+
+
+sos_ret_t sos_irq_set_routine(int irq_level,
+ sos_irq_handler_t routine)
+{
+ sos_ret_t retval;
+ sos_ui32_t flags;
+
+ if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM))
+ return -SOS_EINVAL;
+
+ sos_disable_IRQs(flags);
+
+ retval = SOS_OK;
+
+ /* Set the irq routine to be called by the IRQ wrapper */
+ sos_irq_handler_array[irq_level] = routine;
+
+ /* If the irq is to be enabled, update the IDT with the IRQ
+ wrapper */
+ if (routine != NULL)
+ {
+ retval
+ = sos_idt_set_handler(SOS_IRQ_BASE + irq_level,
+ (sos_vaddr_t) sos_irq_wrapper_array[irq_level],
+ 0 /* CPL0 routine */);
+ /* A problem occured */
+ if (retval != SOS_OK)
+ sos_irq_handler_array[irq_level] = NULL;
+ }
+ else /* Disable this idt entry */
+ {
+ retval
+ = sos_idt_set_handler(SOS_IRQ_BASE + irq_level,
+ (sos_vaddr_t)NULL /* Disable IDTE */,
+ 0 /* Don't care */);
+ }
+
+ /* Update the PIC only if an IRQ handler has been set */
+ if (sos_irq_handler_array[irq_level] != NULL)
+ sos_i8259_enable_irq_line(irq_level);
+ else
+ sos_i8259_disable_irq_line(irq_level);
+
+ sos_restore_IRQs(flags);
+ return retval;
+}
+
+
+sos_irq_handler_t sos_irq_get_routine(int irq_level)
+{
+ if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM))
+ return NULL;
+
+ /* Expected to be atomic */
+ return sos_irq_handler_array[irq_level];
+}
diff --git a/sos-code-article4/hwcore/irq.h b/sos-code-article4/hwcore/irq.h
new file mode 100644
index 0000000..5b39230
--- /dev/null
+++ b/sos-code-article4/hwcore/irq.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2004 David Decotigny
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWINTR_H_
+#define _SOS_HWINTR_H_
+
+/**
+ * @file irq.c
+ *
+ * Hardware interrupts routines management.
+ */
+
+#include <sos/errno.h>
+
+#define sos_save_flags(flags) \
+ asm volatile("pushfl ; popl %0":"=g"(flags)::"memory")
+#define sos_restore_flags(flags) \
+ asm volatile("push %0; popfl"::"g"(flags):"memory")
+
+#define sos_disable_IRQs(flags) \
+ ({ sos_save_flags(flags); asm("cli\n"); })
+#define sos_restore_IRQs(flags) \
+ sos_restore_flags(flags)
+
+/* Usual IRQ levels */
+#define SOS_IRQ_TIMER 0
+#define SOS_IRQ_KEYBOARD 1
+#define SOS_IRQ_SLAVE_PIC 2
+#define SOS_IRQ_COM2 3
+#define SOS_IRQ_COM1 4
+#define SOS_IRQ_LPT2 5
+#define SOS_IRQ_FLOPPY 6
+#define SOS_IRQ_LPT1 7
+#define SOS_IRQ_8_NOT_DEFINED 8
+#define SOS_IRQ_RESERVED_1 9
+#define SOS_IRQ_RESERVED_2 10
+#define SOS_IRQ_RESERVED_3 11
+#define SOS_IRQ_RESERVED_4 12
+#define SOS_IRQ_COPROCESSOR 13
+#define SOS_IRQ_HARDDISK 14
+#define SOS_IRQ_RESERVED_5 15
+
+typedef void (*sos_irq_handler_t)(int irq_level);
+
+/** Setup the PIC */
+sos_ret_t sos_irq_setup(void);
+
+/**
+ * If the routine is not NULL, the IDT is setup to call an IRQ
+ * wrapper upon interrupt, which in turn will call the routine, and
+ * the PIC is programmed to raise an irq.\ If the routine is
+ * NULL, we disable the irq line.
+ */
+sos_ret_t sos_irq_set_routine(int irq_level,
+ sos_irq_handler_t routine);
+
+sos_irq_handler_t sos_irq_get_routine(int irq_level);
+
+#endif /* _SOS_HWINTR_H_ */
diff --git a/sos-code-article4/hwcore/irq_wrappers.S b/sos-code-article4/hwcore/irq_wrappers.S
new file mode 100644
index 0000000..cf3355d
--- /dev/null
+++ b/sos-code-article4/hwcore/irq_wrappers.S
@@ -0,0 +1,173 @@
+/* Copyright (C) 2004 The KOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#define ASM_SOURCE 1
+
+.file "irq_wrappers.S"
+
+.text
+
+/* The address of the table of handlers (defined in irq.c) */
+.extern sos_irq_handler_array
+
+/* The address of the table of wrappers (defined below, and shared
+ with irq.c */
+.globl sos_irq_wrapper_array
+
+
+/* These pre-handlers are for IRQ (Master PIC) */
+.irp id, 0,1,2,3,4,5,6,7
+
+ .p2align 2, 0x90
+
+ sos_irq_wrapper_\id:
+ .type sos_irq_wrapper_\id,@function
+
+ /*
+ * Backup the CPU context
+ */
+
+ /* Fake error code */
+ pushl $0
+
+ /* Backup the actual context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Send EOI to PIC. See Intel 8259 datasheet
+ available on Kos website */
+ movb $0x20, %al
+ outb %al, $0x20
+
+ /*
+ * Call the handler with IRQ number as argument
+ */
+ pushl $\id
+ leal sos_irq_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Remove fake error code */
+ addl $4, %esp
+
+ iret
+ .endr
+
+
+/* These pre-handlers are for IRQ (Slave PIC) */
+.irp id, 8,9,10,11,12,13,14,15
+
+ .p2align 2, 0x90
+
+ sos_irq_wrapper_\id:
+ .type sos_irq_wrapper_\id,@function
+
+ /*
+ * Backup the CPU context
+ */
+
+ /* Fake error code */
+ pushl $0
+
+ /* Backup the actual context */
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ subl $2,%esp
+ pushw %ss
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ /* Send EOI to PIC. See Intel 8259 datasheet
+ available on Kos website */
+ movb $0x20, %al
+ outb %al, $0xa0
+ outb %al, $0x20
+
+ /*
+ * Call the handler with IRQ number as argument
+ */
+ pushl $\id
+ leal sos_irq_handler_array,%edi
+ call *\id*4(%edi)
+ addl $4, %esp
+
+ /* Restore the context */
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popw %ss
+ addl $2,%esp
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /* Remove fake error code */
+ addl $4, %esp
+
+ iret
+ .endr
+
+/* Build the sos_irq_wrapper_array, shared with irq.c */
+.section ".rodata"
+.p2align 5, 0x0
+sos_irq_wrapper_array:
+ .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .long (sos_irq_wrapper_\id)
+ .endr
diff --git a/sos-code-article4/hwcore/paging.c b/sos-code-article4/hwcore/paging.c
new file mode 100644
index 0000000..5968adf
--- /dev/null
+++ b/sos-code-article4/hwcore/paging.c
@@ -0,0 +1,455 @@
+/* Copyright (C) 2004 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <sos/physmem.h>
+#include <sos/klibc.h>
+#include <sos/assert.h>
+
+#include "paging.h"
+
+/** The structure of a page directory entry. See Intel vol 3 section
+ 3.6.4 */
+struct x86_pde
+{
+ sos_ui32_t present :1; /* 1=PT mapped */
+ sos_ui32_t write :1; /* 0=read-only, 1=read/write */
+ sos_ui32_t user :1; /* 0=supervisor, 1=user */
+ sos_ui32_t write_through :1; /* 0=write-back, 1=write-through */
+ sos_ui32_t cache_disabled :1; /* 1=cache disabled */
+ sos_ui32_t accessed :1; /* 1=read/write access since last clear */
+ sos_ui32_t zero :1; /* Intel reserved */
+ sos_ui32_t page_size :1; /* 0=4kB, 1=4MB or 2MB (depending on PAE) */
+ sos_ui32_t global_page :1; /* Ignored (Intel reserved) */
+ sos_ui32_t custom :3; /* Do what you want with them */
+ sos_ui32_t pt_paddr :20;
+} __attribute__ ((packed));
+
+
+/** The structure of a page table entry. See Intel vol 3 section
+ 3.6.4 */
+struct x86_pte
+{
+ sos_ui32_t present :1; /* 1=PT mapped */
+ sos_ui32_t write :1; /* 0=read-only, 1=read/write */
+ sos_ui32_t user :1; /* 0=supervisor, 1=user */
+ sos_ui32_t write_through :1; /* 0=write-back, 1=write-through */
+ sos_ui32_t cache_disabled :1; /* 1=cache disabled */
+ sos_ui32_t accessed :1; /* 1=read/write access since last clear */
+ sos_ui32_t dirty :1; /* 1=write access since last clear */
+ sos_ui32_t zero :1; /* Intel reserved */
+ sos_ui32_t global_page :1; /* 1=No TLB invalidation upon cr3 switch
+ (when PG set in cr4) */
+ sos_ui32_t custom :3; /* Do what you want with them */
+ sos_ui32_t paddr :20;
+} __attribute__ ((packed));
+
+
+/** Structure of the x86 CR3 register: the Page Directory Base
+ Register. See Intel x86 doc Vol 3 section 2.5 */
+struct x86_pdbr
+{
+ sos_ui32_t zero1 :3; /* Intel reserved */
+ sos_ui32_t write_through :1; /* 0=write-back, 1=write-through */
+ sos_ui32_t cache_disabled :1; /* 1=cache disabled */
+ sos_ui32_t zero2 :7; /* Intel reserved */
+ sos_ui32_t pd_paddr :20;
+} __attribute__ ((packed));
+
+
+/**
+ * Helper macro to control the MMU: invalidate the TLB entry for the
+ * page located at the given virtual address. See Intel x86 vol 3
+ * section 3.7.
+ */
+#define invlpg(vaddr) \
+ do { \
+ __asm__ __volatile__("invlpg %0"::"m"(*((unsigned *)(vaddr)))); \
+ } while(0)
+
+
+/**
+ * Helper macro to control the MMU: invalidate the whole TLB. See
+ * Intel x86 vol 3 section 3.7.
+ */
+#define flush_tlb() \
+ do { \
+ unsigned long tmpreg; \
+ asm volatile("movl %%cr3,%0\n\tmovl %0,%%cr3" :"=r" \
+ (tmpreg) : :"memory"); \
+ } while (0)
+
+
+/**
+ * Helper macro to compute the index in the PD for the given virtual
+ * address
+ */
+#define virt_to_pd_index(vaddr) \
+ (((unsigned)(vaddr)) >> 22)
+
+
+/**
+ * Helper macro to compute the index in the PT for the given virtual
+ * address
+ */
+#define virt_to_pt_index(vaddr) \
+ ( (((unsigned)(vaddr)) >> 12) & 0x3ff )
+
+
+/**
+ * Helper macro to compute the offset in the page for the given virtual
+ * address
+ */
+#define virt_to_page_offset(vaddr) \
+ (((unsigned)(vaddr)) & SOS_PAGE_MASK)
+
+
+/**
+ * Helper function to map a page in the pd.\ Suppose that the RAM
+ * is identity mapped to resolve PT actual (CPU) address from the PD
+ * entry
+ */
+static sos_ret_t paging_setup_map_helper(struct x86_pde * pd,
+ sos_paddr_t ppage,
+ sos_vaddr_t vaddr)
+{
+ /* Get the page directory entry and table entry index for this
+ address */
+ unsigned index_in_pd = virt_to_pd_index(vaddr);
+ unsigned index_in_pt = virt_to_pt_index(vaddr);
+
+ /* Make sure the page table was mapped */
+ struct x86_pte * pt;
+ if (pd[index_in_pd].present)
+ {
+ pt = (struct x86_pte*) (pd[index_in_pd].pt_paddr << 12);
+
+ /* If we allocate a new entry in the PT, increase its reference
+ count. This test will always be TRUE here, since the setup
+ routine scans the kernel pages in a strictly increasing
+ order: at each step, the map will result in the allocation of
+ a new PT entry. For the sake of clarity, we keep the test
+ here. */
+ if (! pt[index_in_pt].present)
+ sos_physmem_ref_physpage_at((sos_paddr_t)pt);
+
+ /* The previous test should always be TRUE */
+ else
+ SOS_ASSERT_FATAL(FALSE); /* indicate a fatal error */
+ }
+ else
+ {
+ /* No : allocate a new one */
+ pt = (struct x86_pte*) sos_physmem_ref_physpage_new(FALSE);
+ if (! pt)
+ return -SOS_ENOMEM;
+
+ memset((void*)pt, 0x0, SOS_PAGE_SIZE);
+
+ pd[index_in_pd].present = TRUE;
+ pd[index_in_pd].write = 1; /* It would be too complicated to
+ determine whether it
+ corresponds to a real R/W area
+ of the kernel code/data or
+ read-only */
+ pd[index_in_pd].pt_paddr = ((sos_paddr_t)pt) >> 12;
+ }
+
+
+ /* Map the page in the page table */
+ pt[index_in_pt].present = 1;
+ pt[index_in_pt].write = 1; /* It would be too complicated to
+ determine whether it corresponds to
+ a real R/W area of the kernel
+ code/data or R/O only */
+ pt[index_in_pt].user = 0;
+ pt[index_in_pt].paddr = ppage >> 12;
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_paging_setup(sos_paddr_t identity_mapping_base,
+ sos_paddr_t identity_mapping_top)
+{
+ /* The PDBR we will setup below */
+ struct x86_pdbr cr3;
+
+ /* Get the PD for the kernel */
+ struct x86_pde * pd
+ = (struct x86_pde*) sos_physmem_ref_physpage_new(FALSE);
+
+ /* The iterator for scanning the kernel area */
+ sos_paddr_t paddr;
+
+ /* Reset the PD. For the moment, there is still an IM for the whole
+ RAM, so that the paddr are also vaddr */
+ memset((void*)pd,
+ 0x0,
+ SOS_PAGE_SIZE);
+
+ /* Identity-map the identity_mapping_* area */
+ for (paddr = identity_mapping_base ;
+ paddr < identity_mapping_top ;
+ paddr += SOS_PAGE_SIZE)
+ {
+ if (paging_setup_map_helper(pd, paddr, paddr))
+ return -SOS_ENOMEM;
+ }
+
+ /* Identity-map the PC-specific BIOS/Video area */
+ for (paddr = BIOS_N_VIDEO_START ;
+ paddr < BIOS_N_VIDEO_END ;
+ paddr += SOS_PAGE_SIZE)
+ {
+ if (paging_setup_map_helper(pd, paddr, paddr))
+ return -SOS_ENOMEM;
+ }
+
+ /* Ok, kernel is now identity mapped in the PD. We still have to set
+ up the mirroring */
+ pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].present = TRUE;
+ pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].write = 1;
+ pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].user = 0;
+ pd[virt_to_pd_index(SOS_PAGING_MIRROR_VADDR)].pt_paddr
+ = ((sos_paddr_t)pd)>>12;
+
+ /* We now just have to configure the MMU to use our PD. See Intel
+ x86 doc vol 3, section 3.6.3 */
+ memset(& cr3, 0x0, sizeof(struct x86_pdbr)); /* Reset the PDBR */
+ cr3.pd_paddr = ((sos_paddr_t)pd) >> 12;
+
+ /* Actual loading of the PDBR in the MMU: setup cr3 + bits 31[Paging
+ Enabled] and 16[Write Protect] of cr0, see Intel x86 doc vol 3,
+ sections 2.5, 3.6.1 and 4.11.3 + note table 4-2 */
+ asm volatile ("movl %0,%%cr3\n\t"
+ "movl %%cr0,%%eax\n\t"
+ "orl $0x80010000, %%eax\n\t" /* bit 31 | bit 16 */
+ "movl %%eax,%%cr0\n\t"
+ "jmp 1f\n\t"
+ "1:\n\t"
+ "movl $2f, %%eax\n\t"
+ "jmp *%%eax\n\t"
+ "2:\n\t" ::"r"(cr3):"memory","eax");
+
+ /*
+ * Here, the only memory available is:
+ * - The BIOS+video area
+ * - the identity_mapping_base .. identity_mapping_top area
+ * - the PD mirroring area (4M)
+ * All accesses to other virtual addresses will generate a #PF
+ */
+
+ return SOS_OK;
+}
+
+
+/* Suppose that the current address is configured with the mirroring
+ * enabled to access the PD and PT. */
+sos_ret_t sos_paging_map(sos_paddr_t ppage_paddr,
+ sos_vaddr_t vpage_vaddr,
+ sos_bool_t is_user_page,
+ int flags)
+{
+ /* Get the page directory entry and table entry index for this
+ address */
+ unsigned index_in_pd = virt_to_pd_index(vpage_vaddr);
+ unsigned index_in_pt = virt_to_pt_index(vpage_vaddr);
+
+ /* Get the PD of the current context */
+ struct x86_pde *pd = (struct x86_pde*)
+ (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
+
+ /* Address of the PT in the mirroring */
+ struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*index_in_pd);
+
+ /* The mapping of anywhere in the PD mirroring is FORBIDDEN ;) */
+ if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR)
+ && (vpage_vaddr < SOS_PAGING_MIRROR_VADDR + SOS_PAGING_MIRROR_SIZE))
+ return -SOS_EINVAL;
+
+ /* Map a page for the PT if necessary */
+ if (! pd[index_in_pd].present)
+ {
+ /* No : allocate a new one */
+ sos_paddr_t pt_ppage
+ = sos_physmem_ref_physpage_new(! (flags & SOS_VM_MAP_ATOMIC));
+ if (! pt_ppage)
+ {
+ return -SOS_ENOMEM;
+ }
+
+ pd[index_in_pd].present = TRUE;
+ pd[index_in_pd].write = 1; /* Ignored in supervisor mode, see
+ Intel vol 3 section 4.12 */
+ pd[index_in_pd].user |= (is_user_page)?1:0;
+ pd[index_in_pd].pt_paddr = ((sos_paddr_t)pt_ppage) >> 12;
+
+ /*
+ * The PT is now mapped in the PD mirroring
+ */
+
+ /* Invalidate TLB for the page we just added */
+ invlpg(pt);
+
+ /* Reset this new PT */
+ memset((void*)pt, 0x0, SOS_PAGE_SIZE);
+ }
+
+ /* If we allocate a new entry in the PT, increase its reference
+ count. */
+ else if (! pt[index_in_pt].present)
+ sos_physmem_ref_physpage_at(pd[index_in_pd].pt_paddr << 12);
+
+ /* Otherwise, that means that a physical page is implicitely
+ unmapped */
+ else
+ sos_physmem_unref_physpage(pt[index_in_pt].paddr << 12);
+
+ /* Map the page in the page table */
+ pt[index_in_pt].present = TRUE;
+ pt[index_in_pt].write = (flags & SOS_VM_MAP_PROT_WRITE)?1:0;
+ pt[index_in_pt].user = (is_user_page)?1:0;
+ pt[index_in_pt].paddr = ppage_paddr >> 12;
+ sos_physmem_ref_physpage_at(ppage_paddr);
+
+ /*
+ * The page is now mapped in the current address space
+ */
+
+ /* Invalidate TLB for the page we just added */
+ invlpg(vpage_vaddr);
+
+ return SOS_OK;
+}
+
+
+sos_ret_t sos_paging_unmap(sos_vaddr_t vpage_vaddr)
+{
+ sos_ret_t pt_unref_retval;
+
+ /* Get the page directory entry and table entry index for this
+ address */
+ unsigned index_in_pd = virt_to_pd_index(vpage_vaddr);
+ unsigned index_in_pt = virt_to_pt_index(vpage_vaddr);
+
+ /* Get the PD of the current context */
+ struct x86_pde *pd = (struct x86_pde*)
+ (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
+
+ /* Address of the PT in the mirroring */
+ struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*index_in_pd);
+
+ /* No page mapped at this address ? */
+ if (! pd[index_in_pd].present)
+ return -SOS_EINVAL;
+ if (! pt[index_in_pt].present)
+ return -SOS_EINVAL;
+
+ /* The unmapping of anywhere in the PD mirroring is FORBIDDEN ;) */
+ if ((vpage_vaddr >= SOS_PAGING_MIRROR_VADDR)
+ && (vpage_vaddr < SOS_PAGING_MIRROR_VADDR + SOS_PAGING_MIRROR_SIZE))
+ return -SOS_EINVAL;
+
+ /* Reclaim the physical page */
+ sos_physmem_unref_physpage(pt[index_in_pt].paddr << 12);
+
+ /* Unmap the page in the page table */
+ memset(pt + index_in_pt, 0x0, sizeof(struct x86_pte));
+
+ /* Invalidate TLB for the page we just unmapped */
+ invlpg(vpage_vaddr);
+
+ /* Reclaim this entry in the PT, which may free the PT */
+ pt_unref_retval = sos_physmem_unref_physpage(pd[index_in_pd].pt_paddr << 12);
+ SOS_ASSERT_FATAL(pt_unref_retval >= 0);
+ if (pt_unref_retval > 0)
+ /* If the PT is now completely unused... */
+ {
+ /* Release the PDE */
+ memset(pd + index_in_pd, 0x0, sizeof(struct x86_pde));
+
+ /* Update the TLB */
+ invlpg(pt);
+ }
+
+ return SOS_OK;
+}
+
+
+int sos_paging_get_prot(sos_vaddr_t vaddr)
+{
+ int retval;
+
+ /* Get the page directory entry and table entry index for this
+ address */
+ unsigned index_in_pd = virt_to_pd_index(vaddr);
+ unsigned index_in_pt = virt_to_pt_index(vaddr);
+
+ /* Get the PD of the current context */
+ struct x86_pde *pd = (struct x86_pde*)
+ (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
+
+ /* Address of the PT in the mirroring */
+ struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*index_in_pd);
+
+ /* No page mapped at this address ? */
+ if (! pd[index_in_pd].present)
+ return SOS_VM_MAP_PROT_NONE;
+ if (! pt[index_in_pt].present)
+ return SOS_VM_MAP_PROT_NONE;
+
+ /* Default access right of an available page is "read" on x86 */
+ retval = SOS_VM_MAP_PROT_READ;
+ if (pd[index_in_pd].write && pt[index_in_pt].write)
+ retval |= SOS_VM_MAP_PROT_WRITE;
+
+ return retval;
+}
+
+
+sos_paddr_t sos_paging_get_paddr(sos_vaddr_t vaddr)
+{
+ /* Get the page directory entry and table entry index for this
+ address */
+ unsigned index_in_pd = virt_to_pd_index(vaddr);
+ unsigned index_in_pt = virt_to_pt_index(vaddr);
+ unsigned offset_in_page = virt_to_page_offset(vaddr);
+
+ /* Get the PD of the current context */
+ struct x86_pde *pd = (struct x86_pde*)
+ (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*virt_to_pd_index(SOS_PAGING_MIRROR_VADDR));
+
+ /* Address of the PT in the mirroring */
+ struct x86_pte * pt = (struct x86_pte*) (SOS_PAGING_MIRROR_VADDR
+ + SOS_PAGE_SIZE*index_in_pd);
+
+ /* No page mapped at this address ? */
+ if (! pd[index_in_pd].present)
+ return (sos_paddr_t)NULL;
+ if (! pt[index_in_pt].present)
+ return (sos_paddr_t)NULL;
+
+ return (pt[index_in_pt].paddr << 12) + offset_in_page;
+}
+
diff --git a/sos-code-article4/hwcore/paging.h b/sos-code-article4/hwcore/paging.h
new file mode 100644
index 0000000..38eb81a
--- /dev/null
+++ b/sos-code-article4/hwcore/paging.h
@@ -0,0 +1,120 @@
+/* Copyright (C) 2004 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_PAGING_H_
+#define _SOS_PAGING_H_
+
+/**
+ * @file paging.h
+ *
+ * MMU management routines (arch-dependent). Setup the MMU without
+ * identity-mapping physical<->virtual addresses over the whole
+ * physical address space: a single, restricted and known, area is
+ * identity-mapped, the remaining kernel/user space is not. To access
+ * and manage the MMU translation tables (PD/PT on x86), we rely on a
+ * particular configuration, called "mirroring", where the top-level
+ * translation table (PD on x86) maps itself at a known and fixed (virtual)
+ * address. The only assumption for this to be possible is that the
+ * structure of the translation table entries are compatible at the
+ * different levels of vadddr->paddr translation process (PDE and PTE
+ * on x86 are Ok). Credits go to Christophe Avoinne for that.
+ */
+
+#include <sos/types.h>
+#include <sos/errno.h>
+
+/**
+ * sos_paging_map flags
+ */
+/** Usual virtual memory access rights */
+#define SOS_VM_MAP_PROT_NONE 0
+#define SOS_VM_MAP_PROT_READ (1<<0)
+#define SOS_VM_MAP_PROT_WRITE (1<<1)
+/* EXEC not supported */
+/** Mapping a page may involve an physical page allocation (for a new
+ PT), hence may potentially block */
+#define SOS_VM_MAP_ATOMIC (1<<31)
+
+/** Virtual address where the mirroring takes place */
+#define SOS_PAGING_MIRROR_VADDR 0x3fc00000 /* 1GB - 4MB */
+/** Length of the space reserved for the mirroring in the kernel
+ virtual space */
+#define SOS_PAGING_MIRROR_SIZE (1 << 22) /* 1 PD = 1024 Page Tables = 4MB */
+
+/**
+ * Setup initial page directory structure where the kernel is
+ * identically-mapped, and the mirroring. This routine also
+ * identity-maps the BIOS and video areas, to allow some debugging
+ * text to be printed to the console. Finally, this routine installs
+ * the whole configuration into the MMU.
+ */
+sos_ret_t sos_paging_setup(sos_paddr_t identity_mapping_base,
+ sos_paddr_t identity_mapping_top);
+
+/**
+ * Map the given physical page at the given virtual address in the
+ * current address space.
+ *
+ * @note *IMPORTANT*: The physical page ppage_paddr *MUST* have been
+ * referenced by the caller through either a call to
+ * sos_physmem_ref_physpage_new() or sos_physmem_ref_physpage_at(). It
+ * would work if this were untrue, but this would be INCORRECT (it is
+ * expected that one is owning the page before mapping it, or
+ * otherwise the page could have been stolen by an interrupt or
+ * another thread).
+ *
+ * @param ppage_paddr The address of a physical page (page-aligned)
+ * @param vpage_vaddr The address of the virtual page (page-aligned)
+ * @param is_user_page TRUE when the page is available from user space
+ * @param flags A mask made of SOS_VM_* bits
+ *
+ * @note Unless the SOS_VM_MAP_ATOMIC bit is set in the flags, the
+ * function may potentially block, because a physical page may be
+ * allocated for a new PT.
+ */
+sos_ret_t sos_paging_map(sos_paddr_t ppage_paddr,
+ sos_vaddr_t vpage_vaddr,
+ sos_bool_t is_user_page,
+ int flags);
+
+/**
+ * Undo the mapping from vaddr to the underlying physical page (if any)
+ * @param vpage_vaddr The address of the virtual page (page-aligned)
+ */
+sos_ret_t sos_paging_unmap(sos_vaddr_t vpage_vaddr);
+
+/**
+ * Return the page protection flags (SOS_VM_MAP_PROT_*) associated
+ * with the address, or SOS_VM_MAP_PROT_NONE when page is not mapped
+ */
+int sos_paging_get_prot(sos_vaddr_t vaddr);
+
+/**
+ * Return the physical address of the given virtual address. Since page
+ * at physical addr 0 is not mapped, the NULL result means "page not
+ * mapped".
+ */
+sos_paddr_t sos_paging_get_paddr(sos_vaddr_t vaddr);
+
+/**
+ * Tell whether the address is physically mapped
+ */
+#define sos_paging_check_present(vaddr) \
+ (sos_paging_get_paddr(vaddr) != NULL)
+
+
+#endif /* _SOS_PAGING_H_ */
diff --git a/sos-code-article4/hwcore/segment.h b/sos-code-article4/hwcore/segment.h
new file mode 100644
index 0000000..37bdf5e
--- /dev/null
+++ b/sos-code-article4/hwcore/segment.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_HWSEGS_H_
+#define _SOS_HWSEGS_H_
+
+/**
+ * @file segments.h
+ *
+ * Global and local (GDT/LDT) segment descriptor definition and
+ * structure. These segments map virtual addresses (ie
+ * data/instruction addresses, relative to these segment descriptors)
+ * to linear addresses (ie addresses in the paged-memory space).
+ *
+ * @see Intel x86 doc, vol 3 chapter 3.
+ */
+
+#include <sos/types.h>
+
+/*
+ * Global segment selectors (GDT) for SOS/x86.
+ *
+ * @see gdt.h
+ */
+#define SOS_SEG_NULL 0 /* NULL segment, unused by the procesor */
+#define SOS_SEG_KCODE 1 /* Kernel code segment */
+#define SOS_SEG_KDATA 2 /* Kernel data segment */
+
+
+/**
+ * Helper macro that builds a segment register's value
+ */
+#define SOS_BUILD_SEGMENT_REG_VALUE(desc_privilege,in_ldt,seg_index) \
+ ( (((desc_privilege) & 0x3) << 0) \
+ | (((in_ldt)?1:0) << 2) \
+ | ((seg_index) << 3) )
+
+
+/*
+ * Local segment selectors (LDT) for SOS/x86
+ */
+/* None */
+
+#endif /* _SOS_HWSEGS_H_ */
diff --git a/sos-code-article4/sos/assert.h b/sos-code-article4/sos/assert.h
new file mode 100644
index 0000000..a14ca0b
--- /dev/null
+++ b/sos-code-article4/sos/assert.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2004 The KOS Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ASSERT_H_
+#define _SOS_ASSERT_H_
+
+#include <drivers/bochs.h>
+#include <drivers/x86_videomem.h>
+
+/**
+ * If the expr is FALSE, print a message and halt the machine
+ */
+#define SOS_ASSERT_FATAL(expr) \
+ ({ \
+ int __res=(int)(expr); \
+ if (! __res) { \
+ asm("cli\n"); /* disable interrupts -- x86 only */ \
+ sos_bochs_printf("%s@%s:%d Assertion " # expr " failed\n", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ sos_x86_videomem_printf(24, 0, 12, \
+ "%s@%s:%d Assertion " # expr " failed", \
+ __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+ for (;;) asm("hlt;") ; /* Infinite loop, ie simple system halt */ \
+ } \
+ })
+
+
+#endif /* _SOS_ASSERT_H_ */
diff --git a/sos-code-article4/sos/errno.h b/sos-code-article4/sos/errno.h
new file mode 100644
index 0000000..2c7bada
--- /dev/null
+++ b/sos-code-article4/sos/errno.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_ERRNO_H_
+#define _SOS_ERRNO_H_
+
+/**
+ * @file errno.h
+ *
+ * SOS return value codes and errors.
+ */
+
+/* Positive values of the error codes */
+#define SOS_OK 0 /* No error */
+#define SOS_EINVAL 1 /* Invalid argument */
+#define SOS_ENOSUP 2 /* Operation not supported */
+#define SOS_ENOMEM 3 /* No available memory */
+#define SOS_EFATAL 255 /* Internal fatal error */
+
+/* A negative value means that an error occured. For
+ * example -SOS_EINVAL means that the error was "invalid
+ * argument" */
+typedef int sos_ret_t;
+
+#endif /* _SOS_ERRNO_H_ */
diff --git a/sos-code-article4/sos/klibc.c b/sos-code-article4/sos/klibc.c
new file mode 100644
index 0000000..277a15c
--- /dev/null
+++ b/sos-code-article4/sos/klibc.c
@@ -0,0 +1,271 @@
+/* Copyright (C) 2004 David Decotigny (with INSA Rennes for vsnprintf)
+ Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include "klibc.h"
+
+/* For an optimized version, see BSD sources ;) */
+void *memcpy(void *dst0, const void *src0, register unsigned int size)
+{
+ char *dst;
+ const char *src;
+ for (dst = (char*)dst0, src = (const char*)src0 ;
+ size > 0 ;
+ dst++, src++, size--)
+ *dst = *src;
+ return dst0;
+}
+
+/* ditto */
+void *memset(void *dst0, register int c, register unsigned int length)
+{
+ char *dst;
+ for (dst = (char*) dst0 ;
+ length > 0 ;
+ dst++, length --)
+ *dst = (char)c;
+ return dst0;
+}
+
+int memcmp(const void *s1, const void *s2, sos_size_t len)
+{
+ const unsigned char *c1, *c2;
+ unsigned int i;
+
+ for (i = 0, c1 = s1, c2 = s2; i < len; i++, c1++, c2++)
+ {
+ if(*c1 != *c2)
+ return *c1 - *c2;
+ }
+
+ return 0;
+}
+
+
+unsigned int strlen(register const char *str)
+{
+ unsigned int retval = 0;
+
+ while (*str++)
+ retval++;
+
+ return retval;
+}
+
+
+unsigned int strnlen(const char * s, sos_size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */continue;
+
+ return sc - s;
+}
+
+
+char *strzcpy(register char *dst, register const char *src, register int len)
+{
+ int i;
+
+ if (len <= 0)
+ return dst;
+
+ for (i = 0; i < len; i++)
+ {
+ dst[i] = src[i];
+ if(src[i] == '\0')
+ return dst;
+ }
+
+ dst[len-1] = '\0';
+ return dst;
+}
+
+
+char *strzcat (char *dest, const char *src, sos_size_t n)
+{
+ char *res = dest;
+
+ for ( ; *dest ; dest++);
+
+ for ( ; *src ; src++, dest++) {
+ *dest = *src;
+ n--;
+ if (n <= 0)
+ break;
+ }
+
+ *dest = '\0';
+ return res;
+}
+
+int strcmp(register const char *s1, register const char *s2)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == 0)
+ return (0);
+
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
+
+
+int strncmp(register const char *s1, register const char *s2, register int len)
+{
+ char c1 = '\0', c2 = '\0';
+
+ while (len > 0)
+ {
+ c1 = (unsigned char) *s1++;
+ c2 = (unsigned char) *s2++;
+ if (c1 == '\0' || c1 != c2)
+ return c1 - c2;
+ len--;
+ }
+
+ return c1 - c2;
+}
+
+
+/* I (d2) borrowed and rewrote this for Nachos/INSA Rennes. Thanks to
+ them for having kindly allowed me to do so. */
+int vsnprintf(char *buff, sos_size_t len, const char * format, va_list ap)
+{
+ sos_size_t i, result;
+
+ if (!buff || !format || (len < 0))
+ return -1;
+
+#define PUTCHAR(thechar) \
+ do { \
+ if (result < len-1) \
+ *buff++ = (thechar); \
+ result++; \
+ } while (0)
+
+ result = 0;
+ for(i=0 ; format[i] != '\0' ; i++){
+ switch (format[i])
+ {
+ case '%':
+ i++;
+ switch(format[i])
+ {
+ case '%':
+ {
+ PUTCHAR('%');
+ break;
+ }
+ case 'i':;
+ case 'd':
+ {
+ int integer = va_arg(ap,int);
+ int cpt2 = 0;
+ char buff_int[16];
+
+ if (integer<0)
+ PUTCHAR('-');
+ /* Ne fait pas integer = -integer ici parce que INT_MIN
+ n'a pas d'equivalent positif (int = [-2^31, 2^31-1]) */
+
+ do {
+ int m10 = integer%10;
+ m10 = (m10 < 0)? -m10:m10;
+ buff_int[cpt2++]=(char)('0'+ m10);
+ integer=integer/10;
+ } while(integer!=0);
+
+ for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
+ PUTCHAR(buff_int[cpt2]);
+
+ break;
+ }
+
+ case 'c':
+ {
+ int value = va_arg(ap,int);
+ PUTCHAR((char)value);
+ break;
+ }
+
+ case 's':
+ {
+ char *string = va_arg(ap,char *);
+ if (! string)
+ string = "(null)";
+ for( ; *string != '\0' ; string++)
+ PUTCHAR(*string);
+ break;
+ }
+
+ case 'x':
+ {
+ unsigned int hexa = va_arg(ap,int);
+ unsigned int nb;
+ int i, had_nonzero = 0;
+ for(i=0 ; i < 8 ; i++)
+ {
+ nb = (unsigned int)(hexa << (i*4));
+ nb = (nb >> 28) & 0xf;
+ // Skip the leading zeros
+ if (nb == 0)
+ {
+ if (had_nonzero)
+ PUTCHAR('0');
+ }
+ else
+ {
+ had_nonzero = 1;
+ if (nb < 10)
+ PUTCHAR('0'+nb);
+ else
+ PUTCHAR('a'+(nb-10));
+ }
+ }
+ if (! had_nonzero)
+ PUTCHAR('0');
+ break;
+ }
+ break;
+
+ default:
+ PUTCHAR('%');
+ PUTCHAR(format[i]);
+ }
+ break;
+
+ default:
+ PUTCHAR(format[i]);
+ }
+ }
+
+ *buff = '\0';
+ return result;
+}
+
+
+int snprintf(char * buff, sos_size_t len, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ len = vsnprintf(buff, len, format, ap);
+ va_end(ap);
+
+ return len;
+}
diff --git a/sos-code-article4/sos/klibc.h b/sos-code-article4/sos/klibc.h
new file mode 100644
index 0000000..a8b9d49
--- /dev/null
+++ b/sos-code-article4/sos/klibc.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2003 The KOS Team
+ Copyright (C) 1999 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_KLIBC_H_
+#define _SOS_KLIBC_H_
+
+/**
+ * @file klibc.h
+ *
+ * Basic libc-style support for common useful functions (string.h,
+ * stdarg.h), some with slight non-standard behavior (see comments).
+ */
+
+#include <sos/types.h>
+
+/* string.h functions */
+
+void *memcpy(void *dst, const void *src, register unsigned int size ) ;
+void *memset(void *dst, register int c, register unsigned int length ) ;
+int memcmp(const void *s1, const void *s2, sos_size_t n);
+
+unsigned int strlen( register const char *str) ;
+unsigned int strnlen(const char * s, sos_size_t maxlen);
+
+/**
+ * @note Same as strncpy(), with a slightly different semantic.
+ * Actually, strncpy(3C) says " The result will not be null-terminated
+ * if the length of 'from' is n or more.". Here, 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcpy( register char *dst, register const char *src,
+ register int len ) ;
+
+/**
+ * @note Same as strncat(), with the same semantic : 'dst' is ALWAYS
+ * null-terminated. And its total len will ALWAYS be <= len, with
+ * null-terminating-char included.
+ */
+char *strzcat (char *dest, const char *src,
+ const sos_size_t len);
+
+int strcmp(register const char *s1, register const char *s2 );
+int strncmp(register const char *s1, register const char *s2,
+ register int len );
+
+/* Basic stdarg.h macros. Taken from gcc support files */
+#define __GNUC_VA_LIST
+typedef void *__gnuc_va_list;
+typedef __gnuc_va_list va_list;
+#define __va_rounded_size(TYPE) \
+ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+#define va_start(AP, LASTARG) \
+ (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG)))
+#define va_end(AP) \
+ ((void)0)
+#define va_arg(AP, TYPE) \
+ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
+ *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
+#define __va_copy(dest, src) \
+ (dest) = (src)
+
+/* stdarg.h functions. There might be a non-standard behavior: there
+ will always be a trailing '\0' in the resulting string */
+int vsnprintf(char *, sos_size_t, const char *, va_list);
+int snprintf(char *, sos_size_t, const char *, /*args*/ ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+#endif /* _SOS_KLIBC_H_ */
diff --git a/sos-code-article4/sos/list.h b/sos-code-article4/sos/list.h
new file mode 100644
index 0000000..67e72f3
--- /dev/null
+++ b/sos-code-article4/sos/list.h
@@ -0,0 +1,186 @@
+/* Copyright (C) 2001 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_LIST_H_
+#define _SOS_LIST_H_
+
+/**
+ * @file list.h
+ *
+ * Circular doubly-linked lists implementation entirely based on C
+ * macros
+ */
+
+
+/* *_named are used when next and prev links are not exactly next
+ and prev. For instance when we have next_in_team, prev_in_team,
+ prev_global and next_global */
+
+#define list_init_named(list,prev,next) \
+ ((list) = NULL)
+
+#define list_singleton_named(list,item,prev,next) ({ \
+ (item)->next = (item)->prev = (item); \
+ (list) = (item); \
+})
+
+#define list_is_empty_named(list,prev,next) \
+ ((list) == NULL)
+
+#define list_get_head_named(list,prev,next) \
+ (list)
+
+#define list_get_tail_named(list,prev,next) \
+ ((list)?((list)->prev):NULL)
+
+/* Internal macro : insert before the head == insert at tail */
+#define __list_insert_atleft_named(before_this,item,prev,next) ({ \
+ (before_this)->prev->next = (item); \
+ (item)->prev = (before_this)->prev; \
+ (before_this)->prev = (item); \
+ (item)->next = (before_this); \
+})
+
+/* @note Before_this and item are expected to be valid ! */
+#define list_insert_before_named(list,before_this,item,prev,next) ({ \
+ __list_insert_atleft_named(before_this,item,prev,next); \
+ if ((list) == (before_this)) (list) = (item); \
+})
+
+/** @note After_this and item are expected to be valid ! */
+#define list_insert_after_named(list,after_this,item,prev,next) ({ \
+ (after_this)->next->prev = (item); \
+ (item)->next = (after_this)->next; \
+ (after_this)->next = (item); \
+ (item)->prev = (after_this); \
+})
+
+#define list_add_head_named(list,item,prev,next) ({ \
+ if (list) \
+ list_insert_before_named(list,list,item,prev,next); \
+ else \
+ list_singleton_named(list,item,prev,next); \
+ (list) = (item); \
+})
+
+#define list_add_tail_named(list,item,prev,next) ({ \
+ if (list) \
+ __list_insert_atleft_named(list,item,prev,next); \
+ else \
+ list_singleton_named(list,item,prev,next); \
+})
+
+/** @note NO check whether item really is in list ! */
+#define list_delete_named(list,item,prev,next) ({ \
+ if ( ((item)->next == (item)) && ((item)->prev == (item)) ) \
+ (item)->next = (item)->prev = (list) = NULL; \
+ else { \
+ (item)->prev->next = (item)->next; \
+ (item)->next->prev = (item)->prev; \
+ if ((item) == (list)) (list) = (item)->next; \
+ (item)->prev = (item)->next = NULL; \
+ } \
+})
+
+#define list_pop_head_named(list,prev,next) ({ \
+ typeof(list) __ret_elt = (list); \
+ list_delete_named(list,__ret_elt,prev,next); \
+ __ret_elt; })
+
+/** Loop statement that iterates through all of its elements, from
+ head to tail */
+#define list_foreach_forward_named(list,iterator,nb_elements,prev,next) \
+ for (nb_elements=0, (iterator) = (list) ; \
+ (iterator) && (!nb_elements || ((iterator) != (list))) ; \
+ nb_elements++, (iterator) = (iterator)->next )
+
+/** Loop statement that iterates through all of its elements, from
+ tail back to head */
+#define list_foreach_backward_named(list,iterator,nb_elements,prev,next) \
+ for (nb_elements=0, (iterator) = list_get_tail_named(list,prev,next) ; \
+ (iterator) && (!nb_elements || \
+ ((iterator) != list_get_tail_named(list,prev,next))) ; \
+ nb_elements++, (iterator) = (iterator)->prev )
+
+#define list_foreach_named list_foreach_forward_named
+
+/** True when we exitted early from the foreach loop (ie break) */
+#define list_foreach_early_break(list,iterator,nb_elements) \
+ ((list) && ( \
+ ((list) != (iterator)) || \
+ ( ((list) == (iterator)) && (nb_elements == 0)) ))
+
+/** Loop statement that also removes the item at each iteration */
+#define list_collapse_named(list,iterator,prev,next) \
+ for ( ; ({ ((iterator) = (list)) ; \
+ if (list) list_delete_named(list,iterator,prev,next) ; \
+ (iterator); }) ; )
+
+
+/*
+ * the same macros : assume that the prev and next fields are really
+ * named "prev" and "next"
+ */
+
+#define list_init(list) \
+ list_init_named(list,prev,next)
+
+#define list_singleton(list,item) \
+ list_singleton_named(list,item,prev,next)
+
+#define list_is_empty(list) \
+ list_is_empty_named(list,prev,next)
+
+#define list_get_head(list) \
+ list_get_head_named(list,prev,next) \
+
+#define list_get_tail(list) \
+ list_get_tail_named(list,prev,next) \
+
+/* @note Before_this and item are expected to be valid ! */
+#define list_insert_after(list,after_this,item) \
+ list_insert_after_named(list,after_this,item,prev,next)
+
+/* @note After_this and item are expected to be valid ! */
+#define list_insert_before(list,before_this,item) \
+ list_insert_before_named(list,before_this,item,prev,next)
+
+#define list_add_head(list,item) \
+ list_add_head_named(list,item,prev,next)
+
+#define list_add_tail(list,item) \
+ list_add_tail_named(list,item,prev,next)
+
+/* @note NO check whether item really is in list ! */
+#define list_delete(list,item) \
+ list_delete_named(list,item,prev,next)
+
+#define list_pop_head(list) \
+ list_pop_head_named(list,prev,next)
+
+#define list_foreach_forward(list,iterator,nb_elements) \
+ list_foreach_forward_named(list,iterator,nb_elements,prev,next)
+
+#define list_foreach_backward(list,iterator,nb_elements) \
+ list_foreach_backward_named(list,iterator,nb_elements,prev,next)
+
+#define list_foreach list_foreach_forward
+
+#define list_collapse(list,iterator) \
+ list_collapse_named(list,iterator,prev,next)
+
+#endif /* _SOS_LIST_H_ */
diff --git a/sos-code-article4/sos/macros.h b/sos-code-article4/sos/macros.h
new file mode 100644
index 0000000..b08f081
--- /dev/null
+++ b/sos-code-article4/sos/macros.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2004 The KOS Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_MACROS_H_
+#define _SOS_MACROS_H_
+
+/** Align on a boundary (MUST be a power of 2), so that return value <= val */
+#define SOS_ALIGN_INF(val,boundary) \
+ (((unsigned)(val)) & (~((boundary)-1)))
+
+/** Align on a boundary (MUST be a power of 2), so that return value >= val */
+#define SOS_ALIGN_SUP(val,boundary) \
+ ({ unsigned int __bnd=(boundary); \
+ (((((unsigned)(val))-1) & (~(__bnd - 1))) + __bnd); })
+
+/**
+ * @return TRUE if val is a power of 2.
+ * @note val is evaluated multiple times
+ */
+#define SOS_IS_POWER_OF_2(val) \
+ ((((val) - 1) & (val)) == 0)
+
+#endif /* _SOS_MACROS_H_ */
diff --git a/sos-code-article4/sos/main.c b/sos-code-article4/sos/main.c
new file mode 100644
index 0000000..7f54f70
--- /dev/null
+++ b/sos-code-article4/sos/main.c
@@ -0,0 +1,298 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* Include definitions of the multiboot standard */
+#include <bootstrap/multiboot.h>
+#include <hwcore/idt.h>
+#include <hwcore/gdt.h>
+#include <hwcore/irq.h>
+#include <hwcore/exception.h>
+#include <hwcore/i8254.h>
+#include <sos/list.h>
+#include <sos/physmem.h>
+#include <hwcore/paging.h>
+#include <sos/list.h>
+#include <sos/klibc.h>
+#include <sos/assert.h>
+#include <drivers/x86_videomem.h>
+#include <drivers/bochs.h>
+
+
+/* Helper function to display each bits of a 32bits integer on the
+ screen as dark or light carrets */
+static void display_bits(unsigned char row, unsigned char col,
+ unsigned char attribute,
+ sos_ui32_t integer)
+{
+ int i;
+ /* Scan each bit of the integer, MSb first */
+ for (i = 31 ; i >= 0 ; i--)
+ {
+ /* Test if bit i of 'integer' is set */
+ int bit_i = (integer & (1 << i));
+ /* Ascii 219 => dark carret, Ascii 177 => light carret */
+ unsigned char ascii_code = bit_i?219:177;
+ sos_x86_videomem_putchar(row, col++,
+ attribute,
+ ascii_code);
+ }
+}
+
+
+/* Clock IRQ handler */
+static void clk_it(int intid)
+{
+ static sos_ui32_t clock_count = 0;
+
+ display_bits(0, 48,
+ SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
+ clock_count);
+ clock_count++;
+
+}
+
+/* Page fault exception handler */
+static void pgflt_ex(int exid)
+{
+ sos_bochs_printf("Got page fault\n");
+ sos_x86_videomem_printf(10, 30,
+ SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,
+ "Got EXPECTED (?) Page fault ! But where ???");
+ for (;;) ;
+}
+
+static void test_paging(sos_vaddr_t sos_kernel_core_top_vaddr)
+{
+ /* The (linear) address of the page holding the code we are
+ currently executing */
+ sos_vaddr_t vpage_code = SOS_PAGE_ALIGN_INF(test_paging);
+
+ /* The new physical page that will hold the code */
+ sos_paddr_t ppage_new;
+
+ /* Where this page will be mapped temporarily in order to copy the
+ code into it: right after the kernel code/data */
+ sos_vaddr_t vpage_tmp = sos_kernel_core_top_vaddr;
+
+ unsigned i;
+
+ /* Bind the page fault exception to one of our routines */
+ sos_exception_set_routine(SOS_EXCEPT_PAGE_FAULT,
+ pgflt_ex);
+
+ /*
+ * Test 1: move the page where we execute the code elsewhere in
+ * physical memory
+ */
+ sos_x86_videomem_printf(4, 0,
+ SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
+ "Moving current code elsewhere in physical memory:");
+
+
+ /* Allocate a new physical page */
+ ppage_new = sos_physmem_ref_physpage_new(FALSE);
+ if (! ppage_new)
+ {
+ /* STOP ! No memory left */
+ sos_x86_videomem_putstring(20, 0,
+ SOS_X86_VIDEO_FG_LTRED
+ | SOS_X86_VIDEO_BG_BLUE,
+ "test_paging : Cannot allocate page");
+ return;
+ }
+
+ sos_x86_videomem_printf(5, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Hello from the address 0x%x in physical memory",
+ sos_paging_get_paddr(vpage_code));
+
+ sos_x86_videomem_printf(6, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Transfer vpage 0x%x: ppage 0x%x -> 0x%x (tmp vpage 0x%x)",
+ vpage_code,
+ sos_paging_get_paddr(vpage_code),
+ ppage_new,
+ (unsigned)vpage_tmp);
+
+ /* Map the page somewhere (right after the kernel mapping) in order
+ to copy the code we are currently executing */
+ sos_paging_map(ppage_new, vpage_tmp,
+ FALSE,
+ SOS_VM_MAP_ATOMIC
+ | SOS_VM_MAP_PROT_READ
+ | SOS_VM_MAP_PROT_WRITE);
+
+ /* Ok, the new page is referenced by the mapping, we can release our
+ reference to it */
+ sos_physmem_unref_physpage(ppage_new);
+
+ /* Copy the contents of the current page of code to this new page
+ mapping */
+ memcpy((void*)vpage_tmp,
+ (void*)vpage_code,
+ SOS_PAGE_SIZE);
+
+ /* Transfer the mapping of the current page of code to this new page */
+ sos_paging_map(ppage_new, vpage_code,
+ FALSE,
+ SOS_VM_MAP_ATOMIC
+ | SOS_VM_MAP_PROT_READ
+ | SOS_VM_MAP_PROT_WRITE);
+
+ /* Ok, here we are: we have changed the physcal page that holds the
+ code we are executing ;). However, this new page is mapped at 2
+ virtual addresses:
+ - vpage_tmp
+ - vpage_code
+ We can safely unmap it from sos_kernel_core_top_vaddr, while
+ still keeping the vpage_code mapping */
+ sos_paging_unmap(vpage_tmp);
+
+ sos_x86_videomem_printf(7, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Hello from the address 0x%x in physical memory",
+ sos_paging_get_paddr(vpage_code));
+
+ sos_x86_videomem_printf(9, 0,
+ SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
+ "Provoking a page fault:");
+
+ /*
+ * Test 2: make sure the #PF handler works
+ */
+
+ /* Scan part of the kernel up to a page fault. This page fault
+ should occur on the first page unmapped after the kernel area,
+ which is exactly the page we temporarily mapped/unmapped
+ (vpage_tmp) above to move the kernel code we are executing */
+ for (i = vpage_code ; /* none */ ; i += SOS_PAGE_SIZE)
+ {
+ unsigned *pint = (unsigned *)SOS_PAGE_ALIGN_INF(i);
+ sos_bochs_printf("Test vaddr 0x%x : val=", (unsigned)pint);
+ sos_x86_videomem_printf(10, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Test vaddr 0x%x : val= ",
+ (unsigned)pint);
+ sos_bochs_printf("0x%x\n", *pint);
+ sos_x86_videomem_printf(10, 30,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "0x%x ", *pint);
+ }
+
+ /* BAD ! Did not get the page fault... */
+ sos_x86_videomem_printf(20, 0,
+ SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,
+ "We should have had a #PF at vaddr 0x%x !",
+ vpage_tmp);
+}
+
+/* The C entry point of our operating system */
+void sos_main(unsigned long magic, unsigned long addr)
+{
+ unsigned i;
+ sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr;
+
+ /* Grub sends us a structure, called multiboot_info_t with a lot of
+ precious informations about the system, see the multiboot
+ documentation for more information. */
+ multiboot_info_t *mbi;
+ mbi = (multiboot_info_t *) addr;
+
+ /* Setup bochs and console, and clear the console */
+ sos_bochs_setup();
+
+ sos_x86_videomem_setup();
+ sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
+
+ /* Greetings from SOS */
+ if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
+ /* Loaded with Grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
+ "SOS", ',',
+ (unsigned)(mbi->mem_upper >> 10) + 1,
+ (unsigned)mbi->mem_upper);
+ else
+ /* Not loaded with grub */
+ sos_x86_videomem_printf(1, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Welcome to SOS");
+
+ sos_bochs_putstring("Message in a bochs\n");
+
+ /* Setup CPU segmentation and IRQ subsystem */
+ sos_gdt_setup();
+ sos_idt_setup();
+
+ /* Setup SOS IRQs and exceptions subsystem */
+ sos_exceptions_setup();
+ sos_irq_setup();
+
+ /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */
+ sos_i8254_set_frequency(100);
+
+
+ /* We need a multiboot-compliant boot loader to get the size of the RAM */
+ if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
+ {
+ sos_x86_videomem_putstring(20, 0,
+ SOS_X86_VIDEO_FG_LTRED
+ | SOS_X86_VIDEO_BG_BLUE
+ | SOS_X86_VIDEO_FG_BLINKING,
+ "I'm not loaded with Grub !");
+ /* STOP ! */
+ for (;;)
+ continue;
+ }
+
+ /* Binding some HW interrupts and exceptions to software routines */
+ sos_irq_set_routine(SOS_IRQ_TIMER,
+ clk_it);
+ /* Enabling the HW interrupts here, this will make the timer HW
+ interrupt call our clk_it handler */
+ asm volatile ("sti\n");
+ /* Multiboot says: "The value returned for upper memory is maximally
+ the address of the first upper memory hole minus 1 megabyte.". It
+ also adds: "It is not guaranteed to be this value." aka "YMMV" ;) */
+ sos_physmem_setup((mbi->mem_upper<<10) + (1<<20),
+ & sos_kernel_core_base_paddr,
+ & sos_kernel_core_top_paddr);
+
+ /*
+ * Switch to paged-memory mode
+ */
+
+ /* Disabling interrupts should seem more correct, but it's not really
+ necessary at this stage */
+ if (sos_paging_setup(sos_kernel_core_base_paddr,
+ sos_kernel_core_top_paddr))
+ sos_bochs_printf("Could not setup paged memory mode\n");
+ sos_x86_videomem_printf(2, 0,
+ SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
+ "Paged-memory mode is activated");
+
+ test_paging(sos_kernel_core_top_paddr);
+
+ /* An operatig system never ends */
+ for (;;)
+ continue;
+
+ return;
+}
diff --git a/sos-code-article4/sos/physmem.c b/sos-code-article4/sos/physmem.c
new file mode 100644
index 0000000..99cffb7
--- /dev/null
+++ b/sos-code-article4/sos/physmem.c
@@ -0,0 +1,269 @@
+/* Copyright (C) 2004 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#include <sos/list.h>
+#include <sos/macros.h>
+#include <sos/assert.h>
+#include <sos/klibc.h>
+
+#include "physmem.h"
+
+/** A descriptor for a physical page in SOS */
+struct physical_page_descr
+{
+ /** The physical base address for the page */
+ sos_paddr_t paddr;
+
+ /** The reference count for this physical page. > 0 means that the
+ page is in the used list. */
+ sos_count_t ref_cnt;
+
+ /** The other pages on the list (used, free) */
+ struct physical_page_descr *prev, *next;
+};
+
+/** These are some markers present in the executable file (see sos.lds) */
+extern char __b_kernel, __e_kernel;
+
+/** The array of ppage descriptors will be located at this address */
+#define PAGE_DESCR_ARRAY_ADDR \
+ SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kernel))
+static struct physical_page_descr * physical_page_descr_array;
+
+/** The list of physical pages currently available */
+static struct physical_page_descr *free_ppage;
+
+/** The list of physical pages currently in use */
+static struct physical_page_descr *used_ppage;
+
+/** We will store here the interval of valid physical addresses */
+static sos_paddr_t physmem_base, physmem_top;
+
+/** We store the number of pages used/free */
+static sos_count_t physmem_total_pages, physmem_used_pages;
+
+sos_ret_t sos_physmem_setup(sos_size_t ram_size,
+ /* out */sos_paddr_t *kernel_core_base,
+ /* out */sos_paddr_t *kernel_core_top)
+{
+ /* The iterator over the page descriptors */
+ struct physical_page_descr *ppage_descr;
+
+ /* The iterator over the physical addresses */
+ sos_paddr_t ppage_addr;
+
+ /* Make sure ram size is aligned on a page boundary */
+ ram_size = SOS_PAGE_ALIGN_INF(ram_size);/* Yes, we may lose at most a page */
+
+ /* Reset the used/free page lists before building them */
+ free_ppage = used_ppage = NULL;
+ physmem_total_pages = physmem_used_pages = 0;
+
+ /* Make sure that there is enough memory to store the array of page
+ descriptors */
+ *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_paddr_t)(& __b_kernel));
+ *kernel_core_top
+ = PAGE_DESCR_ARRAY_ADDR
+ + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_PAGE_SHIFT)
+ * sizeof(struct physical_page_descr));
+ if (*kernel_core_top > ram_size)
+ return -SOS_ENOMEM;
+
+ /* Page 0-4kB is not available in order to return address 0 as a
+ means to signal "no page available" */
+ physmem_base = SOS_PAGE_SIZE;
+ physmem_top = ram_size;
+
+ /* Setup the page descriptor arrray */
+ physical_page_descr_array
+ = (struct physical_page_descr*)PAGE_DESCR_ARRAY_ADDR;
+
+ /* Scan the list of physical pages */
+ for (ppage_addr = 0,
+ ppage_descr = physical_page_descr_array ;
+ ppage_addr < physmem_top ;
+ ppage_addr += SOS_PAGE_SIZE,
+ ppage_descr ++)
+ {
+ enum { PPAGE_MARK_RESERVED, PPAGE_MARK_FREE,
+ PPAGE_MARK_KERNEL, PPAGE_MARK_HWMAP } todo;
+
+ memset(ppage_descr, 0x0, sizeof(struct physical_page_descr));
+
+ /* Init the page descriptor for this page */
+ ppage_descr->paddr = ppage_addr;
+
+ /* Reserved : 0 ... base */
+ if (ppage_addr < physmem_base)
+ todo = PPAGE_MARK_RESERVED;
+
+ /* Free : base ... BIOS */
+ else if ((ppage_addr >= physmem_base)
+ && (ppage_addr < BIOS_N_VIDEO_START))
+ todo = PPAGE_MARK_FREE;
+
+ /* Used : BIOS */
+ else if ((ppage_addr >= BIOS_N_VIDEO_START)
+ && (ppage_addr < BIOS_N_VIDEO_END))
+ todo = PPAGE_MARK_HWMAP;
+
+ /* Free : BIOS ... kernel */
+ else if ((ppage_addr >= BIOS_N_VIDEO_END)
+ && (ppage_addr < (sos_paddr_t) (& __b_kernel)))
+ todo = PPAGE_MARK_FREE;
+
+ /* Used : Kernel code/data/bss + physcal page descr array */
+ else if ((ppage_addr >= *kernel_core_base)
+ && (ppage_addr < *kernel_core_top))
+ todo = PPAGE_MARK_KERNEL;
+
+ /* Free : first page of descr ... end of RAM */
+ else
+ todo = PPAGE_MARK_FREE;
+
+ /* Actually does the insertion in the used/free page lists */
+ physmem_total_pages ++;
+ switch (todo)
+ {
+ case PPAGE_MARK_FREE:
+ ppage_descr->ref_cnt = 0;
+ list_add_head(free_ppage, ppage_descr);
+ break;
+
+ case PPAGE_MARK_KERNEL:
+ case PPAGE_MARK_HWMAP:
+ ppage_descr->ref_cnt = 1;
+ list_add_head(used_ppage, ppage_descr);
+ physmem_used_pages ++;
+ break;
+
+ default:
+ /* Reserved page: nop */
+ break;
+ }
+ }
+
+ return SOS_OK;
+}
+
+
+sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block)
+{
+ struct physical_page_descr *ppage_descr;
+
+ if (! free_ppage)
+ return (sos_paddr_t)NULL;
+
+ /* Retrieve a page in the free list */
+ ppage_descr = list_pop_head(free_ppage);
+
+ /* The page is assumed not to be already used */
+ SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);
+
+ /* Mark the page as used (this of course sets the ref count to 1) */
+ ppage_descr->ref_cnt ++;
+
+ /* Put the page in the used list */
+ list_add_tail(used_ppage, ppage_descr);
+ physmem_used_pages ++;
+
+ return ppage_descr->paddr;
+}
+
+
+/**
+ * Helper function to get the physical page descriptor for the given
+ * physical page address.
+ *
+ * @return NULL when out-of-bounds or non-page-aligned
+ */
+inline static struct physical_page_descr *
+get_page_descr_at_paddr(sos_paddr_t ppage_paddr)
+{
+ /* Don't handle non-page-aligned addresses */
+ if (ppage_paddr & SOS_PAGE_MASK)
+ return NULL;
+
+ /* Don't support out-of-bounds requests */
+ if ((ppage_paddr < physmem_base) || (ppage_paddr >= physmem_top))
+ return NULL;
+
+ return physical_page_descr_array + (ppage_paddr >> SOS_PAGE_SHIFT);
+}
+
+
+sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr)
+{
+ struct physical_page_descr *ppage_descr
+ = get_page_descr_at_paddr(ppage_paddr);
+
+ if (! ppage_descr)
+ return -SOS_EINVAL;
+
+ /* Increment the reference count for the page */
+ ppage_descr->ref_cnt ++;
+
+ /* If the page is newly referenced (ie we are the only owners of the
+ page => ref cnt == 1), transfer it in the used pages list */
+ if (ppage_descr->ref_cnt == 1)
+ {
+ list_delete(free_ppage, ppage_descr);
+ list_add_tail(used_ppage, ppage_descr);
+ physmem_used_pages ++;
+
+ /* The page is newly referenced */
+ return FALSE;
+ }
+
+ /* The page was already referenced by someone */
+ return TRUE;
+}
+
+
+sos_ret_t
+sos_physmem_unref_physpage(sos_paddr_t ppage_paddr)
+{
+ /* By default the return value indicates that the page is still
+ used */
+ sos_ret_t retval = FALSE;
+
+ struct physical_page_descr *ppage_descr
+ = get_page_descr_at_paddr(ppage_paddr);
+
+ if (! ppage_descr)
+ return -SOS_EINVAL;
+
+ /* Don't do anything if the page is not in the used list */
+ if (ppage_descr->ref_cnt <= 0)
+ return -SOS_EINVAL;
+
+ /* Unreference the page, and, when no mapping is active anymore, put
+ the page in the free list */
+ ppage_descr->ref_cnt--;
+ if (ppage_descr->ref_cnt <= 0)
+ {
+ /* Transfer the page, considered USED, to the free list */
+ list_delete(used_ppage, ppage_descr);
+ physmem_used_pages --;
+ list_add_head(free_ppage, ppage_descr);
+
+ /* Indicate that the page is now unreferenced */
+ retval = TRUE;
+ }
+
+ return retval;
+}
diff --git a/sos-code-article4/sos/physmem.h b/sos-code-article4/sos/physmem.h
new file mode 100644
index 0000000..8b5d997
--- /dev/null
+++ b/sos-code-article4/sos/physmem.h
@@ -0,0 +1,119 @@
+/* Copyright (C) 2004 David Decotigny
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_PHYSMEM_H_
+#define _SOS_PHYSMEM_H_
+
+/**
+ * @file physmem.h
+ *
+ * Physical pages of memory
+ */
+
+#include <sos/errno.h>
+#include <sos/types.h>
+#include <sos/macros.h>
+
+/** The size of a physical page (arch-dependent) */
+#define SOS_PAGE_SIZE (4*1024)
+
+/** The corresponding shift */
+#define SOS_PAGE_SHIFT 12 /* 4 kB = 2^12 B */
+
+/** The corresponding mask */
+#define SOS_PAGE_MASK ((1<<12) - 1)
+
+#define SOS_PAGE_ALIGN_INF(val) \
+ SOS_ALIGN_INF((val), SOS_PAGE_SIZE)
+#define SOS_PAGE_ALIGN_SUP(val) \
+ SOS_ALIGN_SUP((val), SOS_PAGE_SIZE)
+
+
+/**
+ * This is the reserved physical interval for the x86 video memory and
+ * BIOS area. In physmem.c, we have to mark this area as "used" in
+ * order to prevent from allocating it. And in paging.c, we'd better
+ * map it in virtual space if we really want to be able to print to
+ * the screen (for debugging purpose, at least): for this, the
+ * simplest is to identity-map this area in virtual space (note
+ * however that this mapping could also be non-identical).
+ */
+#define BIOS_N_VIDEO_START 0xa0000
+#define BIOS_N_VIDEO_END 0x100000
+
+
+/**
+ * Initialize the physical memory subsystem, for the physical area [0,
+ * ram_size). This routine takes into account the BIOS and video
+ * areas, to prevent them from future allocations.
+ *
+ * @param ram_size The size of the RAM that will be managed by this subsystem
+ *
+ * @param kernel_core_base The lowest address for which the kernel
+ * assumes identity mapping (ie virtual address == physical address)
+ * will be stored here
+ *
+ * @param kernel_core_top The top address for which the kernel
+ * assumes identity mapping (ie virtual address == physical address)
+ * will be stored here
+ */
+sos_ret_t sos_physmem_setup(sos_size_t ram_size,
+ /* out */sos_paddr_t *kernel_core_base,
+ /* out */sos_paddr_t *kernel_core_top);
+
+/**
+ * Retrieve the total number of pages, and the number of free pages
+ */
+sos_ret_t sos_physmem_get_state(/* out */sos_count_t *total_ppages,
+ /* out */sos_count_t *used_ppages);
+
+
+/**
+ * Get a free page.
+ *
+ * @return The (physical) address of the (physical) page allocated, or
+ * NULL when none currently available.
+ *
+ * @param can_block TRUE if the function is allowed to block
+ * @note The page returned has a reference count equal to 1.
+ */
+sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block);
+
+
+/**
+ * Increment the reference count of a given physical page. Useful for
+ * VM code which tries to map a precise physical address.
+ *
+ * @return TRUE when the page was previously in use, FALSE when the
+ * page was previously in the free list, <0 when the page address is
+ * invalid.
+ */
+sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr);
+
+
+/**
+ * Decrement the reference count of the given physical page. When this
+ * reference count reaches 0, the page is marked free, ie is available
+ * for future sos_physmem_get_physpage()
+ *
+ * @return FALSE when the page is still in use, TRUE when the page is now
+ * unreferenced, <0 when the page address is invalid
+ */
+sos_ret_t sos_physmem_unref_physpage(sos_paddr_t ppage_paddr);
+
+
+#endif /* _SOS_PHYSMEM_H_ */
diff --git a/sos-code-article4/sos/types.h b/sos-code-article4/sos/types.h
new file mode 100644
index 0000000..02d9f6d
--- /dev/null
+++ b/sos-code-article4/sos/types.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 2004 The SOS Team
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+#ifndef _SOS_TYPES_H_
+#define _SOS_TYPES_H_
+
+/**
+ * @file types.h
+ *
+ * SOS basic types definition
+ */
+
+/** Physical address */
+typedef unsigned int sos_paddr_t;
+
+/** Generic virtual address (kernel or user) */
+typedef unsigned int sos_vaddr_t;
+
+/** Memory size of an object (positive) */
+typedef unsigned int sos_size_t;
+/** Generic count of objects */
+typedef unsigned int sos_count_t;
+
+/** Low-level sizes */
+typedef unsigned long int sos_ui32_t; /* 32b unsigned */
+typedef unsigned short int sos_ui16_t; /* 16b unsigned */
+typedef unsigned char sos_ui8_t; /* 8b unsigned */
+
+typedef enum { FALSE=0, TRUE } sos_bool_t;
+
+/** Not a proper type, but highly useful with basic type
+ manipulations */
+#define NULL ((void*)0)
+
+#endif /* _SOS_TYPES_H_ */
diff --git a/sos-code-article4/support/build_image.sh b/sos-code-article4/support/build_image.sh
new file mode 100755
index 0000000..43929cd
--- /dev/null
+++ b/sos-code-article4/support/build_image.sh
@@ -0,0 +1,215 @@
+#!/bin/sh
+# Copyright (C) 2003, David Decotigny
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+# 1) What does it do ?
+#
+# 1) Check where Grub is installed (lookup_grub)
+# 2) Assign some local variables using the shell script arguments.
+# a) Argument 1 : the destination (either a file or a drive, like a:)
+# b) Argument 2 : the loader (i.e kernel)
+# c) Argument 3 : options passed to the loader
+# d) Argument 4 : the modules (that can be loaded optionally by Grub)
+# 3) Test whether destination is a drive or a file
+# 4) Create the directory structure inside the drive
+# 5) Copy the loader in the drive
+# 6) Generate the 'menu.txt' file used by Grub to generate the boot menu
+# 7) Copy all modules
+# 8) Copy the menu.txt file
+#
+# 2) Why is it so complex ?
+# Because it must support various Grub/mtools installations and versions
+#
+# In fact, this shell script is used in the KOS (kos.enix.org)
+# project. This operating system consists in a loader and many many
+# modules that are linked together at boot time. It is much more
+# complex that a simple monolithic kernel.
+#
+# For your simple monolithic kernel, you only need to give argument 1
+# and 2.
+
+print_usage () {
+ echo "Usage: $0 [X:|image] path/to/loader option path/to/modules..."
+ echo " where X: is a valid floppy drive on your computer"
+ echo " where image is any file name"
+ exit 1
+}
+
+grub_dirs_common="/usr/local/share/grub/i386-freebsd /usr/local/share/grub/i386-pc /usr/share/grub/i386-pc /usr/lib/grub/i386-pc /usr/local/grub /usr/share/grub/i386-redhat /usr/local/src/grub-0.5.94 $HOME/share/grub/i386-pc/"
+sbin_grub_path="/usr/local/sbin /usr/sbin /sbin $HOME/sbin"
+
+PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
+export PATH
+
+MTOOLSRC=mtoolsrc
+export MTOOLSRC
+
+# Redefined variables
+FLOPPY_DRIVE=A:
+IMG_FNAME=fd.img
+
+##
+## Format disk image
+##
+init_image () {
+ echo "Initialize disk image $IMG_FILE..."
+ if [ ! -f $IMG_FNAME ] ; then
+ dd if=/dev/zero of=$IMG_FNAME bs=18k count=80 1>/dev/null 2>&1
+ fi
+
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M filter" > $MTOOLSRC
+
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\" 1.44M" > $MTOOLSRC
+ if mformat U: ; then : ; else
+ rm -f $MTOOLSRC
+ echo "drive u: file=\"$IMG_FNAME\"" > $MTOOLSRC
+ mformat U:
+ fi
+ fi
+}
+
+
+##
+## Format (real) floppy disk
+##
+init_floppy () {
+ echo "Formatting floppy..."
+ mformat $FLOPPY_DRIVE || exit 1
+}
+
+
+lookup_grub () {
+ # Look for a correct GRUBDIR
+ for d in $grub_dirs_common ; do
+ if [ -d $d ] ; then
+ GRUBDIR=$d
+ break
+ fi
+ done
+
+ # Try to guess with locate
+ if [ ! -d "$GRUBDIR" ] ; then
+ GRUBDIR=`locate stage2 | head -1 | xargs dirname 2>/dev/null`
+ fi
+
+ # Look for a correct sbin/grub
+ for d in $sbin_grub_path ; do
+ if [ -x $d/grub ] ; then
+ SBIN_GRUB=$d/grub
+ break
+ fi
+ done
+
+ if [ -d "$GRUBDIR" -a -x "$SBIN_GRUB" ] ; then
+ echo "Found correct grub installation in $GRUBDIR"
+ echo "Found correct /sbin/grub at $SBIN_GRUB"
+ else
+ echo "Couldn't find a correct grub installation."
+ exit 1
+ fi
+}
+
+##
+## setup_disk [drive]
+## => setup disk directory structure / copy files
+##
+setup_disk () {
+ echo "Setup destination disk..."
+
+ mmd $1/boot
+ mmd $1/boot/grub
+
+ if [ -d $GRUBDIR/stage1 ] ; then
+ mcopy $GRUBDIR/stage1/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2/stage2 $1/boot/grub/
+ else
+ mcopy $GRUBDIR/stage1 $1/boot/grub/
+ mcopy $GRUBDIR/stage2 $1/boot/grub/
+ fi
+ mmd $1/system
+ mmd $1/modules
+
+ $SBIN_GRUB --batch <<EOT 1>/dev/null 2>/dev/null || exit 1
+device (fd0) $IMG_FNAME
+install (fd0)/boot/grub/stage1 (fd0) (fd0)/boot/grub/stage2 p (fd0)/boot/grub/menu.txt
+quit
+EOT
+}
+
+
+
+#################################################
+## Real start
+##
+#[ "$#" -lt 3 ] && print_usage
+
+lookup_grub
+
+dest="$1" ; shift
+loader_fname="$1" ; shift
+options="$1" ; shift
+modules="$*"
+
+# Init destination disk
+case x$dest in
+ x*:)
+ drive=$dest
+ IMG_FNAME=$dest
+ FLOPPY_DRIVE=$dest
+ init_floppy
+ ;;
+ x*)
+ drive=U:
+ IMG_FNAME=$dest
+ init_image
+ ;;
+esac
+
+# Create directory structure
+setup_disk $drive
+
+# Copy the loader
+mcopy -bo $loader_fname $drive/system/`basename $loader_fname`
+
+# Generate the menu.txt file
+rm -f menu.txt
+cat <<EOF > menu.txt
+timeout 0
+default 0
+title Simple OS
+root (fd0)
+kernel /system/`basename $loader_fname` $options
+EOF
+
+# Copy the modules
+for f in $modules ; do
+ if [ ! -f $f ] ; then
+ echo "ERROR: module $f not correctly compiled in."
+ exit 1
+ fi
+ if ! mcopy -bo $f $drive/modules/`basename $f` ; then
+ echo "ERROR: module $f could not be transferred to floppy."
+ exit 1
+ fi
+ echo module /modules/`basename $f` >> menu.txt
+done
+
+# Transfers the menu.txt file to floppy
+mcopy -bo menu.txt $drive/boot/grub/
diff --git a/sos-code-article4/support/sos.lds b/sos-code-article4/support/sos.lds
new file mode 100644
index 0000000..4d87061
--- /dev/null
+++ b/sos-code-article4/support/sos.lds
@@ -0,0 +1,107 @@
+/* Copyright (C) 2003, Thomas Petazzoni
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+*/
+
+/* We generate binary in the ELF format */
+OUTPUT_FORMAT("elf32-i386","elf32-i386","elf32-i386");
+
+/* The entry point is _start (defined in boot.S) */
+ENTRY(_start)
+
+/* The architecture is i386 */
+OUTPUT_ARCH("i386")
+
+SECTIONS
+{
+ /* our kernel is loaded at 0x200000 */
+ . = 0x200000;
+ __b_load = .;
+
+ /* the multiboot header MUST come early enough in the output
+ object file */
+ .multiboot :
+ {
+ /* The multiboot section (containing the multiboot header)
+ goes here */
+ *(.multiboot);
+
+ /*
+ * With the following line, we force this section to be
+ * allocated in the output file as soon as possible, no matter
+ * when the file containing the multiboot header (multiboot.S)
+ * is compiled. This is to conform to the multiboot spec, which
+ * says "The Multiboot header must be contained completely
+ * within the first 8192 bytes of the OS image, and must be
+ * longword (32-bit) aligned."
+ */
+ LONG(0);
+ }
+
+ /* Defines a symbol '__b_kernel to mark the start of the kernel
+ code/data */
+ . = ALIGN(4096);
+ __b_kernel = .;
+
+ /* Beginning of the text section */
+ .text ALIGN(4096) :
+ {
+ /* This section includes the code */
+ *(.text*)
+ /* Defines the 'etext' and '_etext' at the end */
+ PROVIDE(etext = .);
+ PROVIDE(_etext = .);
+ }
+
+ /* Beginning of the data section */
+ .data . :
+ { *(.data*)
+ PROVIDE(edata = .);
+ PROVIDE(_edata = .);
+ }
+
+ /* Beginning of the read-only data section */
+ .rodata . :
+ { *(.rodata*)
+ PROVIDE(erodata = .);
+ PROVIDE(_erodata = .);
+ }
+ /* We take note of the end of the data to load */
+ __e_load = .;
+
+ /* Beginning of the BSS section (global uninitialized data) */
+ .bss SIZEOF(.rodata) + ADDR(.rodata) :
+ { *(.bss)
+ *(COMMON)
+ PROVIDE(ebss = .);
+ PROVIDE(_ebss = .);
+ }
+
+ /* We take note of the end of the kernel */
+ __e_kernel = .;
+
+ /* We don't care of the note, indent, comment, etc.. sections
+ generated by gcc */
+ /DISCARD/ :{
+ *(.note*)
+ *(.indent)
+ *(.comment)
+ *(.stab)
+ *(.stabstr)
+ }
+
+}
+