[Prev][Next][Index][Thread]
Re: console I/O setup
> I only need the console to work for debugging. All the device and
> network code works (using OsKit) using my implementation of a PXE
> ROM.
There's two choices of lightweight console in the oskit. (There's
also the base_console stuff but it pulls in gdb, getenv, serial, vga,
and all sorts of other stuff that you probably don't want.) I'm not
sure how ROMable they are (what does ROMable mean anyway?)
The VGA console needs no initialisation. The relevant files are:
files{ "kern/x86/pc/direct_cons_putchar.c",
"kern/x86/pc/direct_cons_bell.c",
"kern/x86/pc/pc_speaker.c",
} with cppflags kern;
(The latter 2 are probably not in the version you have.)
If you need the keyboard too, you'll want these files:
files{ "kern/x86/pc/direct_cons_getchar.c"
, "kern/x86/pc/direct_cons_trygetchar.c"
}
The exports from these files are:
direct_cons_putchar
direct_cons_getchar -- blocks for key
direct_cons_trygetchar -- non-blocking getchar
If you use the VGA, you'll probably want to call getchar before
rebooting so you have a chance to read error messages, etc.
Alternatively, you could use the serial console:
files{ "kern/x86/pc/com_cons.c" } with cppflags kern;
which provides:
sig SigCOMConsole =
{ com_cons_enable_receive_interrupt
, com_cons_flush
, com_cons_getchar
, com_cons_init
, com_cons_putchar
, com_cons_trygetchar
}
The com_cons_init function is used to select which serial port to use
(I think - working from memory here - check documentation/ .h files)
To use one of these libraries, you can either write little wrapper
functions such as:
int getchar(void) { return direct_cons_getchar(); }
or use binutils to rename the symbols in the .o files.
You'll probably want printf too (but it adds 2kbytes to your code
size, so you might skip it):
files{ "libc/stdio/doprnt.c"
, "libc/stdio/printf.c"
, "libc/stdio/putchar.c"
, "libc/stdio/puts.c"
}
--
Alastair Reid
ps The above snippets come from my efforts at describing OSKit
components as "units". Here's some more complete descriptions of the
units. There's some redundancy because this is one of the first parts
of the OSKit I "unitised" and I didn't know what I was doing yet.
sig SigPutChar =
{ putchar
, putbytes
}
sig SigGetChar =
{ getchar
}
sig SigConsole =
{ extends SigPutChar
, extends SigGetChar
}
sig SigStdin =
{ getline
, gets
, extends SigGetChar
}
sig SigStdout =
{ printf
, vprintf
, puts
, extends SigPutChar
}
sig SigDirectConsole =
{ direct_cons_getchar
, direct_cons_putchar
, direct_cons_set_flags
, direct_cons_trygetchar
}
-- mk_cpu_unit -o -n raw_VGA kern/direct_cons_putchar.o kern/direct_cons_bell.o kern/pc_speaker.o
unit raw_VGA = {
requires( critical : SigCritical
, vm : SigVM
-- The flags dependency should be removed!
, flags@{ direct_cons_flags } : { direct_cons_flags }
);
provides( out@{ putchar = direct_cons_putchar }
: { putchar }
);
depends{ out : critical, vm,flags };
files{ "kern/x86/pc/direct_cons_putchar.c",
"kern/x86/pc/direct_cons_bell.c",
"kern/x86/pc/pc_speaker.c",
} with cppflags kern;
}
unit putbytes = {
requires( x : { putchar } );
provides( out@{ putchar=x.putchar, putbytes } : SigPutChar );
depends{ out : x };
files{ "cpu/putbytes.c" }
with cppflags libc;
}
-- adds putbytes
-- (Sadly can't be done in the atomic unit because we have to rename things
-- a little.)
unit VGA = {
requires( critical : SigCritical
, vm : SigVM
);
provides( putbytes : SigPutChar );
depends{};
link {
vga = raw_VGA(critical, vm);
putbytes = putbytes(vga);
}
}
-- mk_cpu_unit -o -n KBD kern/direct_cons_getchar.o kern/direct_cons_trygetchar.o
unit KBD = {
requires( critical : SigCritical );
provides( out@
{ getchar = direct_cons_getchar
, trygetchar = direct_cons_trygetchar
, set_flags = direct_cons_set_flags
} : SigDirectGetChar );
depends{ out : critical };
files{ "kern/x86/pc/direct_cons_getchar.c"
, "kern/x86/pc/direct_cons_trygetchar.c"
}
with cppflags kern;
}
-- A putchar/getchar pair - no more, no less.
-- If you're using the VGA, you probably want to use vga_console
-- instead (it has a more useful finalizer).
unit simple_console = {
requires( vga : SigPutChar
, kbd : SigGetChar
);
provides( out@{ putchar=vga.putchar, putbytes=vga.putbytes
, getchar=kbd.getchar
} : SigConsole );
depends{};
link {}
}
-- mk_cpu_unit -o -n direct_console kern/direct_cons_getchar.o kern/direct_cons_trygetchar.o kern/direct_cons_putchar.o kern/direct_cons_bell.o kern/pc_speaker.o
unit direct_console = {
requires( critical : SigCritical
, vm : SigVM
);
provides( console : SigDirectConsole );
depends{ console : critical, vm };
files{ "kern/x86/pc/direct_cons_getchar.c",
"kern/x86/pc/direct_cons_trygetchar.c",
"kern/x86/pc/direct_cons_putchar.c",
"kern/x86/pc/direct_cons_bell.c",
"kern/x86/pc/pc_speaker.c",
} with cppflags kern;
}
-- mk_cpu_unit -o -n com_console kern/com_cons.o
unit com_console = {
requires( termios : SigTermIOS
, critical : SigCritical
, panic : SigPanic
);
provides( console : SigCOMConsole );
depends{ console : termios, critical, panic };
files{ "kern/x86/pc/com_cons.c" } with cppflags kern;
}
-- ToDo: puts should use putbytes (or maybe SigPutChar should include
-- puts as well as putbytes?)
-- mk_cpu_unit -o -n libc_stdout libc/doprnt.o libc/printf.o libc/putchar.o libc/puts.o
unit libc_stdout = {
requires( putchar@
{ putchar=console_putchar
, putbytes=console_putbytes
} : SigPutChar );
provides( stdout : SigStdout );
depends{ stdout : putchar };
files{ "libc/stdio/doprnt.c"
, "libc/stdio/printf.c"
, "libc/stdio/putchar.c"
, "libc/stdio/puts.c"
}
with cppflags libc
}
-- mk_cpu_unit -o -n libc_stdin libc/getline.o libc/getchar.o libc/gets.o
unit libc_stdin = {
requires( console@
{ putchar=console_putchar
, putbytes=console_putbytes
, getchar=console_getchar
} : SigConsole
, stdout : SigStdout
);
provides( stdin : SigStdin );
depends{ stdin : console, stdout };
files{ "libc/gen/getline.c"
, "libc/stdio/getchar.c"
, "libc/stdio/gets.c"
}
with cppflags libc;
}
-- a main program - hello world
unit hello_min = {
requires( stdout : SigStdout );
provides( out@{simplemain=hello} : SigSimpleMain );
depends{ {hello} : stdout };
files { "cpu/hello_min.c" }
with cppflags libc;
}
-- A complete kernel - generates roughly 4kbytes of text
unit Hello = {
requires( ld_symbols : { __oskit_init, __oskit_fini
, _start, end, edata
-- , __ANNO_START__, __ANNO_END__
}
, _exit : { _exit }
);
provides( out@{ multiboot_main_wrapped = multiboot.multiboot_main
, base_stack_end = stack.base_stack_end
, oskit_version_string=version.oskit_version_string
} : { multiboot_main_wrapped, base_stack_end, oskit_version_string }
, invoke : { invoke_main }
-- , { invoke_main=main.simplemain } : { invoke_main }
, reset : SigReset
);
depends{};
link{
main = hello_min(stdout);
stdout = libc_stdout(console); -- really only needs putchar
stdin = libc_stdin(console,stdout);
console = vga_console(vga,kbd,stdout);
vga = VGA(critical,vm);
kbd = KBD(critical);
critical = null_critical();
vm = null_VM();
version = version(stdout);
stack = base_stack();
reset = base_reset(vm);
(exit,atexit) = libc_exit(_exit);
multiboot= multiboot_main'(string,vm);
string = libc_string();
invoke = invoke_simplemain(main,ld_symbols,exit,atexit);
}
}
References: