From 4dbe6a264d7a3bd38ca1ac0921248654a50f1b5e Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 5 Oct 2018 14:36:42 +0200 Subject: user space xterm continued --- Makefile.common | 1 - README.md | 1 - driver/screen.h | 34 +- driver/terminal.c | 4 - kernel/kernel.c | 3 +- ref/OS_Specific_Toolchain.html | 760 +++++++++++++++++++++++++++++++++++++++++ userspace/Makefile | 5 +- userspace/init.c | 1 + userspace/vesa.c | 372 -------------------- userspace/xterm/Makefile | 13 + userspace/xterm/crt0.s | 39 +++ userspace/xterm/terminal.c | 572 +++++++++++++++++++++++++++++++ userspace/xterm/vesa.c | 370 ++++++++++++++++++++ userspace/xterm/xterm.c | 2 + 14 files changed, 1779 insertions(+), 398 deletions(-) create mode 100644 ref/OS_Specific_Toolchain.html delete mode 100644 userspace/vesa.c create mode 100644 userspace/xterm/Makefile create mode 100644 userspace/xterm/crt0.s create mode 100644 userspace/xterm/terminal.c create mode 100644 userspace/xterm/vesa.c create mode 100644 userspace/xterm/xterm.c diff --git a/Makefile.common b/Makefile.common index 3ac16ad..5dee801 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1,5 +1,4 @@ ### explicit rules ### - %.o: %.asm @echo "ASM $@ ..."; nasm -f elf $*.asm -o $@ -f elf -F dwarf -g diff --git a/README.md b/README.md index 06a0495..07f47b9 100644 --- a/README.md +++ b/README.md @@ -137,4 +137,3 @@ 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. - diff --git a/driver/screen.h b/driver/screen.h index e3370cb..691ab8f 100644 --- a/driver/screen.h +++ b/driver/screen.h @@ -13,23 +13,23 @@ #define SCR_CTRL 0x3D4 #define SCR_DATA 0x3D5 -// colors -#define SCR_BLACK 0x0 -#define SCR_BLUE 0x1 -#define SCR_GREEN 0x2 -#define SCR_CYAN 0x3 -#define SCR_RED 0x4 -#define SCR_MAGENTA 0x5 -#define SCR_BROWN 0x6 -#define SCR_GRAY_LIGHT 0x7 -#define SCR_GRAY_DARK 0x8 -#define SCR_BLUE_LIGHT 0x9 -#define SCR_GREEN_LIGHT 0xa -#define SCR_CYAN_LIGHT 0xb -#define SCR_RED_LIGHT 0xc -#define SCR_MAGENTA_LIGHT 0xd -#define SCR_YELLOW 0xe -#define SCR_WHITE 0xf +// COLORS +#define SCR_BLACK 0x0 +#define SCR_BLUE 0x1 +#define SCR_GREEN 0x2 +#define SCR_CYAN 0x3 +#define SCR_RED 0x4 +#define SCR_MAGENTA 0x5 +#define SCR_BROWN 0x6 +#define SCR_GRAY_LIGHT 0x7 +#define SCR_GRAY_DARK 0x8 +#define SCR_BLUE_LIGHT 0x9 +#define SCR_GREEN_LIGHT 0xa +#define SCR_CYAN_LIGHT 0xb +#define SCR_RED_LIGHT 0xc +#define SCR_MAGENTA_LIGHT 0xd +#define SCR_YELLOW 0xe +#define SCR_WHITE 0xf //autoscroll void update_cursor(uint32_t col,uint32_t row); diff --git a/driver/terminal.c b/driver/terminal.c index c399ca0..5f11596 100644 --- a/driver/terminal.c +++ b/driver/terminal.c @@ -4,13 +4,10 @@ // man 4 console_codes // - - #include "terminal.h" #include "kernel/kmalloc.h" #include "driver/screen.h" - #include typedef enum { @@ -553,4 +550,3 @@ void terminal_put(terminal_tty *tty, uint8_t c) tty->screen->update_cursor(tty->x,tty->y); return; } - diff --git a/kernel/kernel.c b/kernel/kernel.c index 66021e2..cf65e18 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -190,8 +190,7 @@ void kernel_main(uint32_t eax,uint32_t ebx) klog("Unix Time = %u seconds",unixtime); klog("Symmetric Multi Processing (SMP) start ... "); -// for(int i=1;i + + +OS Specific Toolchain - OSDev Wiki + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

OS Specific Toolchain

+ + +
+ +
From OSDev Wiki
+ + +
+ + +
+ Jump to: navigation, + search +
+ + +
Difficulty level
Difficulty 3.png
Advanced
+

This tutorial will guide you through creating a toolchain comprising Binutils and GCC that specifically targets your operating system. The instructions below teach Binutils and GCC how to create programs for a hypothetical OS named 'MyOS'. +

Until now you have been using a cross-compiler configured to use an existing generic bare target. This is very convenient when starting out as you get a reliable target and the compiler doesn't make any bad assumptions because it thinks it is targeting an existing operating system. However, when you proceed it becomes useful if the compiler knows it is targeting your operating system and what its customs are. For instance, you can make the compiler define a __myos__ preprocessor macro, know which directories to search for include files in, what special crt*.o files are used when linking against libc, and so on. It also becomes much easier to cross-compile software to your OS when you simply have to invoke x86_64-myos-gcc hello.c -o hello to cross-compile a program. Additionally part of the instructions here can be applied to other software packages that also use the GNU build system, which will help you port existing software. +

This tutorial teaches you how to set up a cross-compiler that specifically targets your OS. This is actually the first step of porting Binutils and GCC to your operating system: Any information you give GCC about your OS will help it run on your OS. Once your OS Specific Toolchain has been set up and you have built your OS with it, you can continue by using the cross-compiler to cross-compile the compiler itself to your OS, assuming your libc and kernel is powerful enough. For more information see Porting GCC to your OS. +

+

Contents

+ +
+

Introduction

+

You need the following before you get started: +

+
  • A build environment that can successfully build a GCC Cross-Compiler. +
  • autoconf (exactly version 2.64) +
  • automake (exactly version 1.11 or 1.11.6) +
  • libtool +
  • The latest Binutils source code. +
  • The latest GCC source code. +
  • Knowledge of the internals of Binutils and GCC. +
  • Knowledge of autoconf and automake. +
  • The dependencies of Binutils and GCC as detailed in GCC Cross-Compiler. +
+

Additionally you will need a C Library as described in a later section. As detailed in Hosted GCC Cross-Compiler, it doesn't need to support much and the functionality can be stubbed, but libgcc will need to believe you have a libc. +

You should decide exactly what targets you'll add to Binutils and GCC. If you have been using a generic i686-elf or x86_64-elf or such target, you'll simply want to swap -elf with -myos and get i686-myos and x86_64-myos. Naturally, don't actually write myos, but rather use the name of your OS converted to lower case. See Target Triplet. +

This tutorial currently only have instructions for adding a new x86 and x86_64 target for myos, but it serves as a good enough example that it should be trivial to add more processors by basing it on these instructions and what other operating systems have done. +

+

Modifying Binutils

+

config.sub

+

This is a file you will modify in the same way for each package. It is a GNU standard file produced by including the line 'AC_CANONICAL_SYSTEM' in a configure.ac that is processed by autoconf, and is designed to convert a canonical name of the form i686-pc-myos into separate variables for the processor, vendor and OS, and also rejects systems it doesn't know about. We simply need to add 'myos' to the list of acceptable operating systems. Find the section that begins with the comment "First accept the basic system types" (it begins '-gnu*') and add '-myos*' to the list. Find a line with some free room and add your entry there. +

+

bfd/config.bfd

+

This file is part of the configuration for libbfd, the back-end to Binutils which provides a consistent interface for many object file formats. Generally, each platform-specific version of Binutils contains a libbfd which only supports the object files normally in use on that system, as otherwise the library would be massive (libbfd can support a _lot_ of object types). We need to associate our os with some particular object types. There is a long list starting 'WHEN ADDING ENTRIES TO THIS MATRIX' with the first line as 'case "${targ}" in'. We need to add our full canonical name to this list, by adding some cases such as: +

+
  i[3-7]86-*-myos*)
+    targ_defvec=i386_elf32_vec
+    targ_selvecs=
+    targ64_selvecs=x86_64_elf64_vec
+    ;;
+#ifdef BFD64
+  x86_64-*-myos*)
+    targ_defvec=x86_64_elf64_vec
+    targ_selvecs=i386_elf32_vec
+    want64=true
+    ;;
+#endif
+

Note: If using binutils-2.24 or older, change i386_elf32_vec to bfd_elf32_i386_vec and x86_64_elf64_vec to bfd_elf64_x86_64_vec. +

Be sure to follow the instructions in the comment block above the list and add your entry beneath the comment "#START OF targmatch.h". If you like, you could support different object formats (look at other entries in the list, and the contents of 'bfd' for hints) and also provide more than one to the targ_selvecs line. For instance, you can support coff object files if you add i386coff_vec to the targ_selvecs list. For some reason, all the x86_64 entries in the file file are wrapped in #ifdef BFD64, it's probably prudent to do it yourself as well. +

+

gas/configure.tgt

+

This file tells the gnu assembler what type of output to generate for each target. It automatically matches the i686 part of your target and generates the correct output for that. We just need to tell it what type of object file to generate for myos. In the section starting 'Assign object format ... case ${generic_target} in' you need to add a line like +

+
  i386-*-myos*)    fmt=elf ;;
+

You should use 'i386' in this line even if you are targeting x86_64. This is the only file where you should do it. It is basically because the variable 'generic_target' is not your canonical target name, but rather a variable generated further up in the configure.tgt file, and it sets the first part to i386 for any i[3-7]86 or x86_64. +

Note: this will use the 'generic' emulation. One side-effect is that gas will interpret slash ('/') as a comment, not as a division operator. This will break any code like "movl $(ADDRESS/PAGE_SIZE), %eax". Using "fmt=elf em=gnu ;;" or "fmt=elf em=linux ;;" will disable slash as a comment character. +

+

ld/configure.tgt

+

This file tells the gnu linker what 'emulation' to use for each target. An emulation is basically a combination of linker script and executable file format. We are going to define our own emulation called elf_i386_myos. We need to add an entry to the case statement here after 'Please try to keep this table in alphabetical order ... case "${targ}" in': +

+
i[3-7]86-*-myos*)
+			targ_emul=elf_i386_myos
+			targ_extra_emuls=elf_i386
+			targ64_extra_emuls="elf_x86_64_myos elf_x86_64"
+			;;
+x86_64-*-myos*)
+			targ_emul=elf_x86_64_myos
+			targ_extra_emuls="elf_i386_myos elf_x86_64 elf_i386"
+			;;
+
  • elf_i386_myos is a 32-bit target for your OS. +
  • elf_x86_64_myos is a 64-bit target for your OS. +
  • elf_i386 is a bare 32-bit target as you had with i686-elf. +
  • elf_x86_64 is a bare 64-bit target for your OS as you had with x86_64-elf. +
+

This setup provides you with a 32-bit toolchain that also can produce 64-bit executables, and a 64-bit toolchain that can also produce 64-bit executables. This comes in handy if you use objcopy, for instance. You can also add targ_extra_emuls entries to specify other targets ld should support. See the ld/configure.tgt file for examples. +

+

ld/emulparams/elf_i386_myos.sh

+

Now we need to actually define our emulation. There is a generic file called ld/genscripts.sh which creates the required linker scripts for our target (you need more than one, depending on shared object usage and the like: I have 13 for a single target). It uses a linker script template (from the ld/scripttempl directory) to do this, and it creates the actual emulation C file from an emulation template (from the ld/emultempl directory). These templates are customised by running a script in the ld/emulparams directory which sets various variables. You are welcome to define your own emulation and linker templates, but I find the ELF ones adequate, given that they can be customised by simply adding a file to the emulparams directory. This is what we are going to do now. The content of the file could be something like: +

+
. ${srcdir}/emulparams/elf_i386.sh
+GENERATE_SHLIB_SCRIPT=yes
+GENERATE_PIE_SCRIPT=yes
+

This script is included by ld/genscripts.sh to customize its behavior through shell variables. We include the base elf_i386.sh script as it sets reasonable defaults. Finally, we override the variables whose defaults we disagree with. +

There are a large number of variables that can be set here to customize your toolchain. Read the documentation and look at existing emulations for further information. These are some of the variables that can be set: +

+
  • GENERATE_SHLIB_SCRIPT=yes|no Whether to generate a linker script for shared libraries. We enable this as you might want it later. The base 32-bit elf script defaults this to disabled for some reason. +
  • GENERATE_PIE_SCRIPT=yes|no Whether to generate a linker script for position independent executables. We enable this as you might want it later. The base 32-bit elf script defaults this to disabled for some reason. +
  • SCRIPT_NAME=name Controls which ld/scripttempl/name.sc script generates our linker scripts. +
  • TEMPLATE_NAME=name Controls which ld/emultempl/name.em script generates our bfd emulation C implementation. +
  • OUTPUT_FORMAT=name The name of the BFD output target we use. +
  • TEXT_START_ADDR=0xvalue Controls where the executable begins in memory. +
+

You can read the base elf_i386.sh script for the defaults of these variables, you can then decide for yourself if you wish to override them for your operating system. +

+

ld/emulparams/elf_x86_64_myos.sh

+

This file is just like the above ld/emulparams/elf_i386_myos.sh but for x86_64. +

+
. ${srcdir}/emulparams/elf_x86_64.sh
+

There is no reason to set GENERATE_SHLIB_SCRIPT and GENERATE_PIE_SCRIPT here as the x86_64 base script enables them by default. +

+

ld/Makefile.am

+

We now just need to tell make how to produce the emulation C file for our specific emulation. Putting the 'targ_emul=elf_i386_myos' line into ld/configure.tgt above implies that your host linker will try to link your target ld executable with an object file called eelf_i386_myos.o. There is a default rule to generate this from eelf_i386_myos.c, so we just need to tell it how to make this eelf_i386_myos.c file. As stated above, we let the genscripts.sh file do the hard work. You need to add makefile rules: +

+
# Add this after eelf_i386.c:
+eelf_i386_myos.c: $(srcdir)/emulparams/elf_i386_myos.sh \
+  $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+       ${GENSCRIPTS} elf_i386_myos "$(tdir_elf_i386_myos)"
+ 
+# Add this after eelf_x86_64.c:
+eelf_x86_64_myos.c: $(srcdir)/emulparams/elf_x86_64_myos.sh \
+  $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+       ${GENSCRIPTS} elf_x86_64_myos "$(tdir_elf_x86_64_myos)"
+

Note: Some parts of the line use normal brackets () whereas other parts use curly braces {}. +

Note: The third line must start with single tab, not spaces, as this is a Makefile. +

You also need to add eelf_i386_myos.c to the ALL_EMULATION_SOURCES list; and you also need to add eelf_x86_64_myos.c to the ALL_64_EMULATION_SOURCES list. +

Note: You must run automake in the ld directory after you modify Makefile.am to regenerate Makefile.in. +

+

Modifying GCC

+

config.sub

+

Similar modification to config.sub in Binutils. +

+

gcc/config.gcc

+

This file defines what needs to be built for each particular target and what to include in the final executable. There are two main sections: one which defines generic options for your operating system, and those which define options specific to your operating system on each individual machine type. +

For the first part, find the 'case ${target} in' line just after '# Common parts for widely ported systems' (around line 617) and add something like: +

+
*-*-myos*)
+  gas=yes
+  gnu_ld=yes
+  default_use_cxa_atexit=yes
+  ;;
+

This states that our operating system by default uses the GNU linker and assembler and that we will provide __cxa_atexit (you will need to provide this in your standard library). +

The second section we need to add to is the architecture-specific one. Find the 'case ${target} in' line just before 'tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h"' (around line 886) and add something like: +

+
i[34567]86-*-myos*)
+    tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h glibc-stdint.h i386/i386elf.h myos.h"
+    ;;
+x86_64-*-myos*)
+    tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h glibc-stdint.h i386/i386elf.h i386/x86-64.h myos.h"
+    ;;
+

This defines which target configuration header files gets used. You can make i386/myos32.h and i386/myos64.h files if desired. +

+

gcc/config/myos.h

+

This header allows you to customize your toolchain using preprocessor macros. The relevant parts of GCC will include this header (as controlled by gcc/config.gcc) and modify the behavior according to your customizations. +

+
/* Useful if you wish to make target-specific GCC changes. */
+#undef TARGET_MYOS
+#define TARGET_MYOS 1
+ 
+/* Default arguments you want when running your
+   i686-myos-gcc/x86_64-myos-gcc toolchain */
+#undef LIB_SPEC
+#define LIB_SPEC "-lc" /* link against C standard library */
+ 
+/* Files that are linked before user code.
+   The %s tells GCC to look for these files in the library directory. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s"
+ 
+/* Files that are linked after user code. */
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+ 
+/* Don't automatically add extern "C" { } around header files. */
+#undef  NO_IMPLICIT_EXTERN_C
+#define NO_IMPLICIT_EXTERN_C 1
+ 
+/* Additional predefined macros. */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS()      \
+  do {                                \
+    builtin_define ("__myos__");      \
+    builtin_define ("__unix__");      \
+    builtin_assert ("system=myos");   \
+    builtin_assert ("system=unix");   \
+    builtin_assert ("system=posix");   \
+  } while(0);
+

libstdc++-v3/crossconfig.m4

+

This file describes how the libstdc++ configure file will examine your operating system and adjust the provided features of libstdc++ accordingly. Add a case similar to +

+
  *-myos*)
+    GLIBCXX_CHECK_COMPILER_FEATURES
+    GLIBCXX_CHECK_LINKER_FEATURES
+    GLIBCXX_CHECK_MATH_SUPPORT
+    GLIBCXX_CHECK_STDLIB_SUPPORT
+    ;;
+

TODO: Examine this design and find out what actually needs to be done here. +

Note: You need to run autoconf in the libstdc++-v3 directory. +

+

libgcc/config.host

+

Find the 'case ${host} in' just prior to 'extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o"' (around line 318) and add the cases: +

+
i[34567]86-*-myos*)
+	extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o"
+	tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
+	;;
+x86_64-*-myos*)
+	extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o"
+	tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
+	;;
+

fixincludes/mkfixinc.sh

+

You should disable fixincludes for your operating system. Find the case statement and add a pattern for your operating system. For instance: +

+
# Check for special fix rules for particular targets
+case $machine in
+    *-myos* | \
+    i?86-*-cygwin* | \
+	# (... snip ...)
+    powerpcle-*-eabi* )
+	#  IF there is no include fixing,
+	#  THEN create a no-op fixer and exit
+	(echo "#! /bin/sh" ; echo "exit 0" ) > ${target}
+        ;;
+

A number of operating systems (especially older and obscure ones) provide troublesome systems headers that fail to strictly comply with various standards. The GCC developers consider it their job to fix these headers. GCC will look into your system root, apply a bunch of patterns to detect headers it doesn't like, then it copies that header into a private GCC system directory (that overrides your standard system directory) and attempts to fix the header. Sometimes fixincludes even break working headers (some people refer to it as breakincludes). +

This is rather inconvenient as your libc will likely happen to trigger these patterns (and false positives often happens). Any time you change your system headers, you have to rebuild your compiler so the fixed versions get updated. The first time you encounter this, it will show up as a system header that does nothing different even though you edit it. +

This addition to the mkfixinc.sh file forcefully disables fixincludes for your operating system. It's your job to provide working system headers, not the compiler developers'. +

+

Further Customization

+

TODO: Document more various tips and tricks for further customization of OS specific toolchains. +

+

Changing the Default Include Directory

+

If you wish to change the default include directory from /usr/include, you can override the native_system_header_dir variable in gcc/config.gcc in the case for your OS. +

+

Changing the Default Library Directory

+

If you wish to change the default library directory from /usr/lib, you can change it to /lib by adding the following block of code to the case just below the declaration of NATIVE_LIB_DIRS in binutils/ld/configure.tgt (around line 785). +

+
*-*-myos*)
+  NATIVE_LIB_DIRS='/lib /local/lib'
+  ;;
+

Start Files Directory

+

You can modify which directory GCC looks for the crt0.o, crti.o and crtn.o in. The path to that directory is stored in STANDARD_STARTFILE_PREFIX. For instance, if you change the library directory to /lib in Binutils and want GCC to match, you can add the following to gcc/config/myos.h: +

+
#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/lib/"
+

Note that the trailing slash is important as the raw crt*.o names are appended without first adding a slash. +

+

Linker Options

+

You can modify the arguments passed to the linker using LINK_SPEC. This can be used to force 4KB alignment of sections on 64 bit systems, as ld defaults to 2MB alignment. +

+
/* Tell ld to force 4KB pages*/
+#undef LINK_SPEC
+#define LINK_SPEC "-z max-page-size=4096"
+

Selecting a C Library

+
Main article: C Library +
+

At this point, you have to decide which C Library to use. You have options: +

+ +

Building

+
Main article: Hosted GCC Cross-Compiler +
+

Your OS specific toolchain is built differently from the introductory i686-elf toolchain as it has a user-space and standard library. In particular, you need to ensure your libc meets the minimum requirements for libgcc. You need to install the standard library headers into your System Root before building the cross-compiler. You need to tell the cross-binutils and cross-gcc where the system root is via the configure option --with-sysroot=/path/to/sysroot. You can then build your libc with your cross-compiler and then finally libstdc++ if desired. +

+

Conclusion

+

You now have a i686-myos toolchain that can be used instead of your old i686-elf toolchain. Your new toolchain is effectively just a renamed i686-elf with customizations. You should switch all your operating system build scripts to use this new compiler, even the kernel and libk, as your new compiler is capable of providing a freestanding environment. +

You will certainly wish to package up your custom toolchain (and be able to create a diff between the upstream version and your custom version for others to audit). Contributors should be able to download tarballs of your myos-binutils and myos-gcc packages, so they can build themselves your custom toolchain. +

+

Common errors

+

Whitespaces

+

Some files need tabs, some files need spaces and some files accept happily any mixture. Use an editor that can display special chars such as tabs and spaces, to be sure you use the right form. Whitespace errors may result in 'make' reporting missing separators. Some editors will replace a tab with four spaces, which will also cause invalid separator issues. +

+

Autoconf

+

There are several steps that conclude in running 'autoconf' or 'automake', 'autoreconf', be sure you did not miss them. The order of autoconf/-reconf calls in a package is important. These errors may result in missing subdirectories of the build-* directory and/or 'make' reporting missing targets. +

+

See Also

+

Articles

+ + + + + +
+ + + + + +
+ + +
+ +
+ + +
+ + +
+
Personal tools
+ +
+ + +
+ + +
+
Namespaces
+ +
+ + + + +
+
Variants
+ +
+ + +
+
+ + +
+
Views
+ +
+ + + + +
+
Actions
+ +
+ + + + + + + +
+
+ + +
+ + + + + +
+
Navigation
+ +
+ + + + +
+
About
+ +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + diff --git a/userspace/Makefile b/userspace/Makefile index 3b7a6b9..b1b077d 100644 --- a/userspace/Makefile +++ b/userspace/Makefile @@ -7,6 +7,7 @@ GIT_REVISION=$(shell git rev-parse HEAD) CC=i686-foolos-gcc CC=i686-elf-gcc AS=i686-elf-as + CC = @echo "Compiling (i686-elf-gcc) $<..."; i686-elf-gcc AS = @echo "Assembling (i686-elf-as) $<..."; i686-elf-as @@ -29,9 +30,9 @@ include ../Makefile.common all: crt0.o ext2.img - ext2.img: $(PROGS) make -C fonts + make -C xterm @echo "----------------------" @echo "Creating ext2.img ...." @dd if=/dev/zero of=ext2.img bs=1024 count=$(IMAGESIZE) @@ -48,6 +49,7 @@ ext2.img: $(PROGS) @mkdir -p mnt/pipes # mountpoint for pipes @cp $(PROGS) mnt/bin @cp fonts/binfont.bin mnt/doc/fonts + @cp xterm/xterm mnt/bin # cp ~/temp/fool-os-stuff/binutils-build-host-foolos/binutils/readelf mnt/bin # cp ../font/binfont.bin mnt/ @@ -69,6 +71,7 @@ ext2.img: $(PROGS) clean: make -C fonts clean + make -C xterm clean @echo "Cleaning userspace ..."; rm -f *.o $(PROGS) ext2.img *.d new: clean all diff --git a/userspace/init.c b/userspace/init.c index 0e0fd66..d07942b 100644 --- a/userspace/init.c +++ b/userspace/init.c @@ -6,6 +6,7 @@ int main(int argc, char **argv) { // loop forever and spawn shells if the top-shell exits + _execve("/bin/xterm",NULL,NULL); _execve("/bin/vesa",NULL,NULL); diff --git a/userspace/vesa.c b/userspace/vesa.c deleted file mode 100644 index 7901b1f..0000000 --- a/userspace/vesa.c +++ /dev/null @@ -1,372 +0,0 @@ -#include -#include -#include -#include "newcalls.h" - -#define VMEM_USER_FRAMEBUFFER 0xfa000000 - -typedef struct foolfont_struct -{ - uint8_t line[10]; //every single fool font consists of 10 lines a 8 bit - -}foolfont; - -static foolfont deffont[256]; - -//static vbemodeinfo *VbeModeInfoBlock; - -static int console_x; -static int console_y; - -static int console_lines; -static int console_cols; - -static uint8_t* buffer; -static uint8_t* physbase; - -void PutConsoleNL(); -void PutPixel(int x,int y, int color); - -// we need to obtain this from somewhere else.. -static uint32_t vesaXres; -static uint32_t vesaYres; -static uint32_t vesaPitch; -static uint32_t vesaBpp; -static uint32_t vesaAddr; - -//static char buf[80][24]; - -void vesa_update_cursor(uint32_t col,uint32_t row) -{ - console_x=col; - console_y=row; -} - -// helper_funcs -/* -static void vesa_print_char_col(int x, int y, char c, char col_fg, char col_bg) -{ - // uint16_t attrib = (col_bg << 4) | (col_fg & 0x0F); - // uint16_t* video_mem=(uint16_t *)SCR_VIDEOMEM+(x+y*SCR_REAL_WIDTH); - // *video_mem=c | (attrib << 8) ; -} -*/ - -// same colors as in screen.h -static uint32_t cols[] = { - 0x0, // black - 0x0066cc, //blue - 0x009900, //green - 0x33ffff, //cyan - 0xff3333, //red - 0xcc00cc, //magenta - 0x994c00, //brown - 0xa0a0a0, //light gray - 0x404040, //dark gray - 0x3399ff, //light blue - 0x99ff33, //light green - 0x99ffff, //cyan light - 0xff9999, //red light - 0xff99ff, //magenta light - 0xffff00, //yellow - 0xffffff, //white -}; - -// glue func for terminal -void vesa_console_put_char(uint8_t c,uint8_t color_bg, uint8_t color_fg, uint32_t x, uint32_t y) -{ -// print_char_col(x,y,c, color_bg, color_fg); - //PutFont(c, console_x*10,console_y*12, cols[color_fg],cols[color_bg]); - - //PutFont(c, x*10,y*12, cols[color_bg],cols[color_fg]); - PutFont(c, x*8,y*11, cols[color_bg],cols[color_fg]); - -// buf[console_x][console_y]=c; - -// console_x++; - -// #ifdef FOOLOS_CONSOLE_AUTOBREAK -// if(console_x>=console_cols)PutConsoleNL(); -// #endif -} - -void vesa_switch_buffers() -{ - for(int i=0;i<800*600*2;i++)physbase[i]=buffer[i]; -} - -void vesa_put_rect(int x, int y, int w , int h, int color) -{ - for(int i=x;iframebuffer_type - - /* - vesaXres=inf->framebuffer_width; - vesaYres=inf->framebuffer_height; - vesaPitch=inf->framebuffer_pitch; - vesaBpp=inf->framebuffer_bpp; - vesaAddr=inf->framebuffer_addr; - */ - - // virtual screen - vesaXres=640; - vesaYres=480; - vesaPitch=640*4; - vesaBpp=32; - vesaAddr=VMEM_USER_FRAMEBUFFER; - - //the only functionallu important init lines! (rest is log) - //VbeModeInfoBlock=mode; -// deffont=rawfont; - console_x=0; - console_y=0; - - int line_height=12; - int col_width=10; - - console_lines=vesaYres/line_height; - console_cols=vesaXres/col_width; - - //TODO dynamic (but need to sync with terminal!) - console_cols=80; - console_lines=24; - /* - // vesa info - klog("vbe version: 0x%x / video mode ptr: 0x%x 0x%x", - info->VbeVersion, info->VideoModePtr[1], info->VideoModePtr[0]); - - // vesa info on selected mode: - klog("colors r:%d 0x%x g:%d 0x%x b:%d 0x%x", - mode->red_position,mode->red_mask, - mode->green_position,mode->green_mask, - mode->blue_position,mode->blue_mask); - - klog("res: %d * %d / banks: %d / attr: 0x%x", - mode->Xres, mode->Yres, mode->banks, mode->attributes); - klog("bpp: %d / physbase: 0x%x", - mode->bpp,mode->physbase); - - // vesa modes - // todo: take segment from vbeinfo! -#ifdef FOOLSOS_SHOW_VESAMODES - uint16_t *modeptr=info->VideoModePtr[0]; - - while(*modeptr!=0xffff&&*modeptr!=0) - { - klog("mode supported : 0x%X", (*modeptr)); - modeptr++; - } -#endif -*/ - - return vesaAddr; -} - - -// TODO: what will happen in 24bit mode? -void PutPixel(int x,int y, int color) -{ - //do not write memory outside the screen buffer, check parameters against the VBE mode info - if (x<0 || x>vesaXres|| y<0 || y>vesaYres) return; - if (x) x = (x*(vesaBpp>>3)); // get bytes (divide by 8) - if (y) y = (y*vesaPitch); - //uint8_t *cTemp=VbeModeInfoBlock->physbase; - uint8_t *cTemp=VMEM_USER_FRAMEBUFFER; - - cTemp[x+y] = (uint8_t)(color & 0xff); - cTemp[x+y+1] = (uint8_t)((color>>8) & 0xff); - cTemp[x+y+2] = (uint8_t)((color>>16) & 0xff); -} - - -void PutFont(char c, int x,int y, int color_fg,int color_bg) -{ - - int fnt=0x126-0x20; - - if(c>=0x20&&c<=0x126)fnt=c-0x20; - - int posx, posy, sizex=8, sizey=10; - - for(posx=x;posx=console_cols)PutConsoleNL(); - #endif -} - -void PutConsole(char *str, int color) -{ - - while((*str)!=0) - { - PutConsoleChar(*str,color); - str++; - } - -} -void PutConsoleNL() -{ - console_y++; - if(console_yvesaXres-100)boxx=100; - // if(boxy>VbeModeInfoBlock->Yres-200)boxy=200; - - vesa_switch_buffers(); -} - -/* -void vesa_init_doublebuff() -{ - boxx=300; - boxy=300; - - int blocks=800*600*2/4096+1; - physbase=VbeModeInfoBlock->physbase; - buffer=pmmngr_alloc_blocks(blocks); - klog("Init buffer of %d blocks at 0x%08X",blocks,buffer); - - VbeModeInfoBlock->physbase=buffer; -} -*/ - - - -int main() -{ - FILE *f=fopen("/doc/fonts/binfont.bin","r"); - fread(deffont,10,95,f); - - vesa_init(); - - _gui_win(); - - while(1) - { - vesa_console_put_char('X' ,15, 0, 5, 5); - _gui_rect(); - } - -} diff --git a/userspace/xterm/Makefile b/userspace/xterm/Makefile new file mode 100644 index 0000000..3056094 --- /dev/null +++ b/userspace/xterm/Makefile @@ -0,0 +1,13 @@ +CC=i686-foolos-gcc +AS=i686-foolos-as + +CFLAGS=-I/home/miguel/temp/foolos/usr/i686-foolos/include + +LDFLAGS=-L/home/miguel/temp/foolos/usr/i686-foolos/lib/ + +all: crt0.o xterm + +xterm: vesa.o terminal.o + +clean: + rm -f *.o xterm diff --git a/userspace/xterm/crt0.s b/userspace/xterm/crt0.s new file mode 100644 index 0000000..dedc86c --- /dev/null +++ b/userspace/xterm/crt0.s @@ -0,0 +1,39 @@ +.global _start + +_start: + +# copy reent to this page +push %ebx +push %ecx + +mov _impure_ptr,%eax +mov $0xf5000000,%ebx +copy: +mov (%eax),%ecx +mov %ecx,(%ebx) +add $4, %ebx +add $4, %eax +cmp $0xf5001000,%ebx +jne copy + +pop %ecx +pop %ebx + +movl $0xf5000000, _impure_ptr + +# environment adress was passed on stack + +pop %eax +mov %eax, environ + +# call main (argc and argv are on the stack) +call main + +# push exit code and pass to _exit syscall +push %eax +call exit + +# this should never be reached! +.wait: + hlt +jmp .wait diff --git a/userspace/xterm/terminal.c b/userspace/xterm/terminal.c new file mode 100644 index 0000000..4f321dd --- /dev/null +++ b/userspace/xterm/terminal.c @@ -0,0 +1,572 @@ +// http://en.wikipedia.org/wiki/VT52 +// http://vt100.net/docs/vt520-rm/ +// man 4 console_codes + +#include +#include +#include + +#define NPAR_START 1000 +#define TERM_WIDTH 80 +#define TERM_HEIGHT 24 + +// COLORS +#define SCR_BLACK 0x0 +#define SCR_BLUE 0x1 +#define SCR_GREEN 0x2 +#define SCR_CYAN 0x3 +#define SCR_RED 0x4 +#define SCR_MAGENTA 0x5 +#define SCR_BROWN 0x6 +#define SCR_GRAY_LIGHT 0x7 +#define SCR_GRAY_DARK 0x8 +#define SCR_BLUE_LIGHT 0x9 +#define SCR_GREEN_LIGHT 0xa +#define SCR_CYAN_LIGHT 0xb +#define SCR_RED_LIGHT 0xc +#define SCR_MAGENTA_LIGHT 0xd +#define SCR_YELLOW 0xe +#define SCR_WHITE 0xf +// + +typedef enum{ + + ecma48_reset, + ecma48_bold, + ecma48_halfbright, + ecma48_underscore, + ecma48_blink, + ecma48_reverse_video, + ecma48_reset_mapping, + ecma48_null_mapping_1, + ecma48_null_mapping_2, + ecma48_normalbright_1, + ecma48_normalbright_2, + ecma48_nounderline, + ecma48_blinkoff, + ecma48_reverse_video_off, + + ecma48_fg_black =30, + ecma48_fg_red, + ecma48_fg_green, + ecma48_fg_brown, + ecma48_fg_blue, + ecma48_fg_magenta, + ecma48_fg_cyan, + ecma48_fg_white, + ecma48_underscore_on, // set def color + ecma48_underscore_off, // set def color + + ecma48_bg_black, //40 + ecma48_bg_red, + ecma48_bg_green, + ecma48_bg_brown, + ecma48_bg_blue, + ecma48_bg_magenta, + ecma48_bg_cyan, + ecma48_bg_white, + + ecma48_bg_default =49, + +}terminal_settings; + +typedef struct term_out_struct +{ + void (*put_char)(uint8_t c,uint8_t color_fg, uint8_t color_bg, uint32_t x, uint32_t y); + void (*update_cursor)(uint32_t col,uint32_t row); +}term_out; + +typedef struct term_in_struct +{ + void (*put_char)(uint8_t c); +}term_in; + +typedef struct terminal_tty_struct +{ + uint8_t fg; + uint8_t bg; + + bool set_buff; + bool set_lfnl; + bool set_echo; + + uint32_t width; + uint32_t height; + uint32_t x; + uint32_t y; + uint32_t *data; // screen data + uint8_t *command; // command line / also holds npar for escape sequences somewhere + int32_t command_l; // command line length + + uint8_t escaping; // escaping mode? + uint8_t npar; // npar pos + + term_out *screen; + term_in *input; + + bool reverse_video; + +}terminal_tty; + +static uint32_t index(terminal_tty *tty, uint32_t x, uint32_t y) +{ + return tty->width*y+x; +} + +static void set_char(terminal_tty *tty, uint32_t x, uint32_t y, uint8_t c, uint8_t fg, uint8_t bg) +{ + tty->data[index(tty,x,y)]=c; + tty->data[index(tty,x,y)]|=fg<<8; + tty->data[index(tty,x,y)]|=bg<<16; + tty->screen->put_char(c,fg,bg,x,y); +} + +static void process_graphic_npar(terminal_tty *tty, terminal_settings s) +{ + uint8_t buf; + + switch(s) + { + case ecma48_null_mapping_2: + break; + case ecma48_null_mapping_1: + break; + case ecma48_reset_mapping: + break; + case ecma48_blinkoff: + break; + case ecma48_blink: + break; + case ecma48_nounderline: + break; + case ecma48_underscore_on: + break; + case ecma48_underscore_off: + break; + case ecma48_underscore: + break; + case ecma48_halfbright: + break; + case ecma48_normalbright_1: + break; + case ecma48_normalbright_2: + break; + case ecma48_bold: + break; + case ecma48_reset: + tty->fg=SCR_WHITE; + tty->bg=SCR_BLACK; + break; + + case ecma48_reverse_video: + + if(tty->reverse_video)break; + buf=tty->fg; + tty->fg=tty->bg; + tty->bg=buf; + break; + + case ecma48_reverse_video_off: + + if(!tty->reverse_video)break; + buf=tty->fg; + tty->fg=tty->bg; + tty->bg=buf; + break; + + //fg + + case ecma48_fg_black: + tty->fg=SCR_BLACK; + break; + + case ecma48_fg_red: + tty->fg=SCR_RED; + break; + + case ecma48_fg_green: + tty->fg=SCR_GREEN; + break; + + case ecma48_fg_brown: + tty->fg=SCR_BROWN; + break; + + case ecma48_fg_blue: + tty->fg=SCR_BLUE; + break; + + case ecma48_fg_magenta: + tty->fg=SCR_MAGENTA; + break; + + case ecma48_fg_cyan: + tty->fg=SCR_CYAN; + break; + + case ecma48_fg_white: + tty->fg=SCR_WHITE; + break; + // bg + + case ecma48_bg_black: + tty->bg=SCR_BLACK; + break; + + case ecma48_bg_red: + tty->bg=SCR_RED; + break; + + case ecma48_bg_green: + tty->bg=SCR_GREEN; + break; + + case ecma48_bg_brown: + tty->bg=SCR_BROWN; + break; + + case ecma48_bg_blue: + tty->bg=SCR_BLUE; + break; + + case ecma48_bg_magenta: + tty->bg=SCR_MAGENTA; + break; + + case ecma48_bg_cyan: + tty->bg=SCR_CYAN; + break; + + case ecma48_bg_white: + tty->bg=SCR_WHITE; + break; + + case ecma48_bg_default: + tty->bg=SCR_BLACK; + break; + + } +} + +static void process_graphic_npars(terminal_tty *tty) +{ + + char buf[4]; + int b=0; + + tty->escaping=0; + + for(int i=0;inpar+1;i++) + { + char c=tty->command[NPAR_START+i]; + buf[b++]=c; + + if(i==tty->npar||c==';') + { + if(b==2)process_graphic_npar(tty,buf[0]-'0'); + if(b==3)process_graphic_npar(tty,(buf[0]-'0')*10+(buf[1]-'0')); + b=0; + } + //terminal_put(tty,tty->command[NPAR_START+i]); + } + + tty->npar=0; + +} + +static void reset(terminal_tty *tty) +{ + tty->bg=SCR_BLACK; + tty->fg=SCR_WHITE; + + for(int x=0;xwidth;x++) + for(int y=0;yheight;y++) + { + set_char(tty,x,y,' ',tty->fg,tty->bg); + } + + tty->x=0; + tty->y=0; + tty->command_l=0; +} + +terminal_tty terminal_init(term_out *screen,term_in *input) +{ + terminal_tty tty; + + tty.data=malloc(2*4096); + + tty.set_buff=true; +// tty.set_buff=false; + + tty.set_lfnl=true; +// tty.set_lfnl=false; + + + tty.set_echo=true; + tty.set_echo=false; + + tty.command=malloc(1*4096); + tty.command_l=0; + + tty.escaping=0; + + tty.screen=screen; + tty.input=input; + + tty.x=0; + tty.y=0; + + tty.width=TERM_WIDTH; + tty.height=TERM_HEIGHT; + + tty.reverse_video=false; + + reset(&tty); + + return tty; +} + +// send one ASCII character to the terminal +void terminal_put(terminal_tty *tty, uint8_t c) +{ + + // CONTROL CHARACTERS + if(c==0x07){return;} // BEL (ignore) + if(c==0x7F){return;} // nothing + + if(c==0x09) // TAB + { + if(tty->x==tty->width-1)return; + set_char(tty,tty->x,tty->y,' ',tty->fg,tty->bg); + tty->x++; + + while(tty->xwidth-1&&tty->x%8!=0) + { + set_char(tty,tty->x,tty->y,' ',tty->fg,tty->bg); + tty->x++; + } + tty->x--; + c=' '; + } + + if(c==0x0E){return;} // G1 set (ignore) + if(c==0x0F){return;} // G0 set (ignore) + + if(c==0x18||c==0x1A){tty->escaping=0;return;} // cancel escaping + if(c==0x1B){tty->escaping=1;return;} // ESC + if(c==0x9B){tty->escaping=2;tty->npar=0;return;} // CSI = ESC [ + + if(c==0x08) //BACKSPACE + { + if((tty->x>0&&tty->command_l>0)||!tty->set_echo) + { + set_char(tty,tty->x-1,tty->y,' ',tty->fg,tty->bg); + tty->x--; + } + } + + else if(c==0x0D) // CR + { + tty->x=0; + return; + } + + else if(c==0x0A||c==0x0B||c==0x0C) // \n NEXTLINE + { + for(uint32_t x=tty->x;xwidth;x++) + { + set_char(tty,x,tty->y,' ',tty->fg,tty->bg); + } + tty->y++; + if(tty->set_lfnl)tty->x=0; + } + else // + { + // ESC- but not CSI-sequences + if(tty->escaping==1) + { + // FOOL-TERM: delchar + if(c=='x') + { + set_char(tty, tty->x, tty->y, ' ', tty->fg, tty->bg); + } + // FOOL-TERM: clear to end of line + if(c=='K') + { + for(uint32_t x=tty->x;xwidth;x++) + { + set_char(tty, x, tty->y, ' ', tty->fg, tty->bg); + } + } + // FOOL-TERM: clear to end of screen + if(c=='J') + { + for(uint32_t x=tty->x;xwidth;x++) + { + set_char(tty, x, tty->y, ' ', tty->fg, tty->bg); + } + for(uint32_t y=tty->y+1;yheight;y++) + { + for(uint32_t x=0;xwidth;x++) + { + set_char(tty,x, y, ' ', tty->fg, tty->bg); + } + } + } + + // FOOL-TERM: home + if(c=='H') + { + tty->x=0; + tty->y=0; + } + // FOOL-TERM: movement + if(c=='u') + { + if(tty->y>0) + tty->y--; + } + + if(c=='d') + { + if(tty->y+1height) + tty->y++; + } + + if(c=='f') + { + if(tty->x+1width) + tty->x++; + } + + if(c=='b') + { + if(tty->x>0) + tty->x--; + } + + /// + + if(c=='c'){reset(tty);} // RESET + + if(c=='D'){tty->y++;} // LINEFEED + if(c=='E'){tty->y++;tty->x=0;} //NEWLINE + + //if(c=='H'){} // SET TABSTOP: TODO + if(c=='M'){ // REVERSE LINEFEED + + if(tty->y==0) + { + for(int32_t y=tty->height-1;y>=0;y--) + { + for(uint32_t x=0;xwidth;x++) + { + uint32_t c=' '|tty->fg<<8|tty->bg<<16; + if(y!=0) c=tty->data[index(tty,x,y-1)]; + tty->data[index(tty,x,y)] = c; + + tty->screen->put_char(c&0xff,(c>>8)&0xff,c>>16,x,y); + } + } + } + else + tty->y--; + + } + + if(c=='Z'){// IDENTIFY: claim we are vt102 + + if(tty->input!=NULL) + { + tty->input->put_char(0x1B); //ESC + tty->input->put_char('['); + tty->input->put_char('?'); + tty->input->put_char('6'); + tty->input->put_char('c'); + } + + return;} + + if(c=='7'){}// SAVE STATE (coord,attributes,G0/G1?) + if(c=='8'){}// RESTORE STATE + if(c=='['){tty->escaping=2;tty->npar=0;return;} // CONTROL SEQ INTRODUCER + + + // TODO + // %, %@, %G, %8, #8, (, (B, (O, (U, (K + // ), >, =, ] (???) + // + // + + tty->escaping=0; // DONE + } + // CSI SEQEUENCES (AFTER ESC [..) + else if(tty->escaping==2) + { + //ECMA-48: TODO + + + + + //ECMA-48 GRAPHIC RENDITION: OK + if(c!='m') + { + tty->command[NPAR_START+(tty->npar++)]=c; + } + else + { + process_graphic_npars(tty); + } + + //ECMA-48 MODE SWITCHES: TODO + //ECMA-48 STATUS REPORT: TODO + //DEC PRIVATE MODE: TODO + //LINUX CONSOLE PRIVATE CSI: TODO + // + // ESC [ 1 ; n ] Set color n as the underline color + // ESC [ 2 ; n ] Set color n as the dim color + // ESC [ 8 ] Make the current color pair the default attributes. + // ESC [ 9 ; n ] Set screen blank timeout to n minutes. + // ESC [ 10 ; n ] Set bell frequency in Hz. + // ESC [ 11 ; n ] Set bell duration in msec. + // ESC [ 12 ; n ] Bring specified console to the front. + // ESC [ 13 ] Unblank the screen. + // ESC [ 14 ; n ] Set the VESA powerdown interval in minutes. + + } + else //PROBABLY (AND HOPEFULLY) JUST A NORMAL CHAR + { + set_char(tty,tty->x,tty->y,c,tty->fg,tty->bg); + tty->x++; + } + + } + + //autobreak + if(tty->x>=tty->width) + { + tty->x=0; + tty->y++; + } + + //autoscroll + if(tty->y>=tty->height) + { + tty->y--; + for(uint32_t y=0;yheight;y++) + { + for(uint32_t x=0;xwidth;x++) + { + uint32_t c=tty->data[index(tty,x,y+1)]; + if(y==tty->height-1)c=' '|tty->fg<<8|tty->bg<<16; + tty->data[index(tty,x,y)] = c; + tty->screen->put_char(c&0xff,(c>>8)&0xff,c>>16,x,y); + } + } + } + + //cusor pos + tty->screen->update_cursor(tty->x,tty->y); + return; +} diff --git a/userspace/xterm/vesa.c b/userspace/xterm/vesa.c new file mode 100644 index 0000000..d38f3f2 --- /dev/null +++ b/userspace/xterm/vesa.c @@ -0,0 +1,370 @@ +#include +#include +#include +#include "../newcalls.h" + +#define VMEM_USER_FRAMEBUFFER 0xfa000000 + +typedef struct foolfont_struct +{ + uint8_t line[10]; //every single fool font consists of 10 lines a 8 bit + +}foolfont; + +static foolfont deffont[256]; + +//static vbemodeinfo *VbeModeInfoBlock; + +static int console_x; +static int console_y; + +static int console_lines; +static int console_cols; + +static uint8_t* buffer; +static uint8_t* physbase; + +void PutConsoleNL(); +void PutPixel(int x,int y, int color); + +// we need to obtain this from somewhere else.. +static uint32_t vesaXres; +static uint32_t vesaYres; +static uint32_t vesaPitch; +static uint32_t vesaBpp; +static uint32_t vesaAddr; + +//static char buf[80][24]; + +void vesa_update_cursor(uint32_t col,uint32_t row) +{ + console_x=col; + console_y=row; +} + +// helper_funcs +/* +static void vesa_print_char_col(int x, int y, char c, char col_fg, char col_bg) +{ + // uint16_t attrib = (col_bg << 4) | (col_fg & 0x0F); + // uint16_t* video_mem=(uint16_t *)SCR_VIDEOMEM+(x+y*SCR_REAL_WIDTH); + // *video_mem=c | (attrib << 8) ; +} +*/ + +// same colors as in screen.h +static uint32_t cols[] = { + 0x0, // black + 0x0066cc, //blue + 0x009900, //green + 0x33ffff, //cyan + 0xff3333, //red + 0xcc00cc, //magenta + 0x994c00, //brown + 0xa0a0a0, //light gray + 0x404040, //dark gray + 0x3399ff, //light blue + 0x99ff33, //light green + 0x99ffff, //cyan light + 0xff9999, //red light + 0xff99ff, //magenta light + 0xffff00, //yellow + 0xffffff, //white +}; + +// glue func for terminal +void vesa_console_put_char(uint8_t c,uint8_t color_bg, uint8_t color_fg, uint32_t x, uint32_t y) +{ +// print_char_col(x,y,c, color_bg, color_fg); + //PutFont(c, console_x*10,console_y*12, cols[color_fg],cols[color_bg]); + + //PutFont(c, x*10,y*12, cols[color_bg],cols[color_fg]); + PutFont(c, x*8,y*11, cols[color_bg],cols[color_fg]); + +// buf[console_x][console_y]=c; + +// console_x++; + +// #ifdef FOOLOS_CONSOLE_AUTOBREAK +// if(console_x>=console_cols)PutConsoleNL(); +// #endif +} + +void vesa_switch_buffers() +{ + for(int i=0;i<800*600*2;i++)physbase[i]=buffer[i]; +} + +void vesa_put_rect(int x, int y, int w , int h, int color) +{ + for(int i=x;iframebuffer_type + + /* + vesaXres=inf->framebuffer_width; + vesaYres=inf->framebuffer_height; + vesaPitch=inf->framebuffer_pitch; + vesaBpp=inf->framebuffer_bpp; + vesaAddr=inf->framebuffer_addr; + */ + + // virtual screen + vesaXres=640; + vesaYres=480; + vesaPitch=640*4; + vesaBpp=32; + vesaAddr=VMEM_USER_FRAMEBUFFER; + + //the only functionallu important init lines! (rest is log) + //VbeModeInfoBlock=mode; +// deffont=rawfont; + console_x=0; + console_y=0; + + int line_height=12; + int col_width=10; + + console_lines=vesaYres/line_height; + console_cols=vesaXres/col_width; + + //TODO dynamic (but need to sync with terminal!) + console_cols=80; + console_lines=24; + /* + // vesa info + klog("vbe version: 0x%x / video mode ptr: 0x%x 0x%x", + info->VbeVersion, info->VideoModePtr[1], info->VideoModePtr[0]); + + // vesa info on selected mode: + klog("colors r:%d 0x%x g:%d 0x%x b:%d 0x%x", + mode->red_position,mode->red_mask, + mode->green_position,mode->green_mask, + mode->blue_position,mode->blue_mask); + + klog("res: %d * %d / banks: %d / attr: 0x%x", + mode->Xres, mode->Yres, mode->banks, mode->attributes); + klog("bpp: %d / physbase: 0x%x", + mode->bpp,mode->physbase); + + // vesa modes + // todo: take segment from vbeinfo! +#ifdef FOOLSOS_SHOW_VESAMODES + uint16_t *modeptr=info->VideoModePtr[0]; + + while(*modeptr!=0xffff&&*modeptr!=0) + { + klog("mode supported : 0x%X", (*modeptr)); + modeptr++; + } +#endif +*/ + + return vesaAddr; +} + + +// TODO: what will happen in 24bit mode? +void PutPixel(int x,int y, int color) +{ + //do not write memory outside the screen buffer, check parameters against the VBE mode info + if (x<0 || x>vesaXres|| y<0 || y>vesaYres) return; + if (x) x = (x*(vesaBpp>>3)); // get bytes (divide by 8) + if (y) y = (y*vesaPitch); + //uint8_t *cTemp=VbeModeInfoBlock->physbase; + uint8_t *cTemp=VMEM_USER_FRAMEBUFFER; + + cTemp[x+y] = (uint8_t)(color & 0xff); + cTemp[x+y+1] = (uint8_t)((color>>8) & 0xff); + cTemp[x+y+2] = (uint8_t)((color>>16) & 0xff); +} + + +void PutFont(char c, int x,int y, int color_fg,int color_bg) +{ + + int fnt=0x126-0x20; + + if(c>=0x20&&c<=0x126)fnt=c-0x20; + + int posx, posy, sizex=8, sizey=10; + + for(posx=x;posx=console_cols)PutConsoleNL(); + #endif +} + +void PutConsole(char *str, int color) +{ + + while((*str)!=0) + { + PutConsoleChar(*str,color); + str++; + } + +} +void PutConsoleNL() +{ + console_y++; + if(console_yvesaXres-100)boxx=100; + // if(boxy>VbeModeInfoBlock->Yres-200)boxy=200; + + vesa_switch_buffers(); +} + +/* +void vesa_init_doublebuff() +{ + boxx=300; + boxy=300; + + int blocks=800*600*2/4096+1; + physbase=VbeModeInfoBlock->physbase; + buffer=pmmngr_alloc_blocks(blocks); + klog("Init buffer of %d blocks at 0x%08X",blocks,buffer); + + VbeModeInfoBlock->physbase=buffer; +} +*/ + +int main() +{ + FILE *f=fopen("/doc/fonts/binfont.bin","r"); + fread(deffont,10,95,f); + + vesa_init(); + + _gui_win(); + + while(1) + { + vesa_console_put_char('X' ,15, 0, 5, 5); + _gui_rect(); + } + +} diff --git a/userspace/xterm/xterm.c b/userspace/xterm/xterm.c new file mode 100644 index 0000000..10b222c --- /dev/null +++ b/userspace/xterm/xterm.c @@ -0,0 +1,2 @@ +#include + -- cgit v1.2.3