Mercurial > lcfOS
changeset 16:ddefe6d97cd7
Merged
author | windel-eee |
---|---|
date | Fri, 18 Nov 2011 14:41:53 +0100 |
parents | de004f808e56 (current diff) a58904747019 (diff) |
children | f3e3e0e9c4bc |
files | cos/images/first64bits.img cos/include/ctype.h cos/include/kernel.h cos/include/stdarg.h |
diffstat | 13 files changed, 554 insertions(+), 214 deletions(-) [+] |
line wrap: on
line diff
--- a/cos/Makefile Tue Nov 15 07:35:00 2011 +0100 +++ b/cos/Makefile Fri Nov 18 14:41:53 2011 +0100 @@ -1,8 +1,8 @@ # vim: set noexpandtab: -all: lcfosc.elf +all: bootdisk.img Makefile -bootdisk.img: lcfosc.elf grub/menu.lst +bootdisk.img: lcfosc.elf grub/menu.lst Makefile objcopy -O binary lcfosc.elf lcfosc.bin cp grub/emptybootdisk.img bootdisk.img mcopy -D o -i bootdisk.img lcfosc.bin :: @@ -16,20 +16,24 @@ -nostdlib \ -nostartfiles \ -fno-builtin \ + -mcmodel=large \ -Iinclude OBJECTS = \ kernel/video.o \ kernel/snprintf.o \ - kernel/kernel.o + kernel/kernel.o \ + kernel/asmcode.o \ + kernel/handlers.o + lcfosc.elf: $(CRT0) $(OBJECTS) linker.ld ld -T linker.ld -o lcfosc.elf $(CRT0) $(OBJECTS) -%.o : %.asm +%.o : %.asm Makefile nasm -f elf64 -o $@ $< -%.o : %.c +%.o : %.c Makefile gcc $(CFLAGS) -o $@ -c $< -Wall -Wextra -Werror clean:
--- a/cos/bochsrc.txt Tue Nov 15 07:35:00 2011 +0100 +++ b/cos/bochsrc.txt Fri Nov 18 14:41:53 2011 +0100 @@ -65,7 +65,7 @@ #display_library: win32, options="gui_debug" # use Win32 debugger gui #display_library: wx #display_library: x, options="hideIPS" # disable IPS output in status bar -#display_library: x, options="gui_debug" # use GTK debugger gui +display_library: x, options="gui_debug" # use GTK debugger gui #======================================================================= # ROMIMAGE: @@ -859,7 +859,7 @@ # Example: # magic_break: enabled=1 #======================================================================= -#magic_break: enabled=1 +magic_break: enabled=1 #======================================================================= # PORT_E9_HACK:
--- a/cos/grub/menu.lst Tue Nov 15 07:35:00 2011 +0100 +++ b/cos/grub/menu.lst Fri Nov 18 14:41:53 2011 +0100 @@ -1,5 +1,5 @@ default 0 -timeout 10 +timeout 3 title lcfosc root (fd0) kernel /lcfosc.bin
--- a/cos/include/ctype.h Tue Nov 15 07:35:00 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -#ifndef _LINUX_CTYPE_H -#define _LINUX_CTYPE_H - -/* - * NOTE! This ctype does not handle EOF like the standard C - * library is required to. - */ - -#define _U 0x01 /* upper */ -#define _L 0x02 /* lower */ -#define _D 0x04 /* digit */ -#define _C 0x08 /* cntrl */ -#define _P 0x10 /* punct */ -#define _S 0x20 /* white space (space/lf/tab) */ -#define _X 0x40 /* hex digit */ -#define _SP 0x80 /* hard space (0x20) */ - -extern unsigned char _ctype[]; - -#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) - -#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) -#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) -#define iscntrl(c) ((__ismask(c)&(_C)) != 0) -#define isdigit(c) ((__ismask(c)&(_D)) != 0) -#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) -#define islower(c) ((__ismask(c)&(_L)) != 0) -#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) -#define ispunct(c) ((__ismask(c)&(_P)) != 0) -#define isspace(c) ((__ismask(c)&(_S)) != 0) -#define isupper(c) ((__ismask(c)&(_U)) != 0) -#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) - -#define isascii(c) (((unsigned char)(c))<=0x7f) -#define toascii(c) (((unsigned char)(c))&0x7f) - -static inline unsigned char tolower(unsigned char c) -{ - if (isupper(c)) - c -= 'A'-'a'; - return c; -} - -static inline unsigned char toupper(unsigned char c) -{ - if (islower(c)) - c -= 'a'-'A'; - return c; -} - -#endif
--- a/cos/include/kernel.h Tue Nov 15 07:35:00 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -#ifndef KERNEL_H -#define KERNEL_H - -// Include common functions, available to all! -#define NULL ((void*)0) - -// Type defs: -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -typedef unsigned short ushort_t; -typedef unsigned char uchar_t; -typedef unsigned int uint_t; -typedef unsigned long ulong_t; -typedef unsigned long long ulonglong_t; -typedef unsigned long off_t; -typedef unsigned long size_t; - -void printf(const char* fmt, ... ); -void memset(void* ptr, uint32_t value, uint32_t num); -void memcpy(void* dst, void* src, uint32_t num); - -// memory alloc functions: -void* malloc(size_t size); -void free(void* ptr); - -void clear_screen(); -void init_screen(); -void print_string(const char *); - -// For IO ports: -unsigned char inb(unsigned short); -void outb(unsigned short, unsigned char); - -void setupIDT(void); -void PICremap(void); -// Assembler util functions: -void enableinterrupts(void); -void callint49(void); -void doCPUID(int eax, int *ebx, int *ecx, int *edx); - -// Keyboard driver: -void keyboardDriverUpdate(unsigned char scancode); -void timerDriverUpdate(void); - -// Memory functions: -void mappage(uint32_t address); - -int querymode(void); -int getcs(void); -void loadPageTable(void* tableAddress); -void enablePaging(void); - -struct multiboot_aout_symbol_table { - uint32_t tabsize; - uint32_t strsize, addr, reserved; -}; - -struct multiboot_info { - uint32_t flags; // Multiboot flags / version - uint32_t mem_lower; // available memory from BIOS - uint32_t mem_upper; - uint32_t boot_device; - uint32_t cmdline; // COmmand line - uint32_t mods_count; - uint32_t mods_addr; - union { - struct multiboot_aout_symbol_table aout_sym; - } u; - - uint32_t mmap_length; - uint32_t mmap_addr; -}; - -struct memory_map { - uint32_t size; - uint32_t baselow, basehigh; - uint32_t lenlow, lenhigh; - uint32_t type; -}; - -typedef struct { - char name[32]; // Name of the console - unsigned char screendata[80*25]; // All chars in the console! -} console_t; - -typedef struct { - uint32_t esp; - uint32_t ss; - uint32_t kstack; - uint32_t ustack; - uint32_t cr3; - - uint32_t number; - uint32_t parent; - uint32_t owner; - uint32_t groups; - uint32_t timetorun; - uint32_t sleep; - uint32_t priority; - uint32_t filehandle; - char naam[32]; - - console_t *console; -} programma_t; - -#endif -
--- a/cos/include/stdarg.h Tue Nov 15 07:35:00 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* -Copyright (C) 1988 Free Software Foundation - -This file is part of GNU CC. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY. No author or distributor -accepts responsibility to anyone for the consequences of using it -or for whether it serves any particular purpose or works at all, -unless he says so in writing. Refer to the GNU CC General Public -License for full details. - -Everyone is granted permission to copy, modify and redistribute -GNU CC, but only under the conditions described in the -GNU CC General Public License. A copy of this license is -supposed to have been given to you along with GNU CC so you -can know your rights and responsibilities. It should be in a -file named COPYING. Among other things, the copyright notice -and this notice must be preserved on all copies. -*/ - -#ifndef __stdarg_h -#define __stdarg_h - -typedef char *va_list; - -// In a 64 bits kernel we are using 64 bits pointers: -#define STACKITEM long - -/* Amount of space required in an argument list for an arg of type TYPE. - TYPE may alternatively be an expression whose type is used. */ - -#define __va_rounded_size(TYPE) \ - (((sizeof (TYPE) + sizeof (STACKITEM) - 1) / sizeof (STACKITEM)) * sizeof (STACKITEM)) - -#define va_start(AP, LASTARG) \ - (AP = ((char *) &(LASTARG) + __va_rounded_size(LASTARG))) - -#define va_end(AP) /* Nothing */ - -#define va_arg(AP, TYPE) (AP += __va_rounded_size (TYPE), \ - *((TYPE *) (AP - __va_rounded_size (TYPE)))) - -#endif /* __stdarg_h */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/kernel/asmcode.asm Fri Nov 18 14:41:53 2011 +0100 @@ -0,0 +1,76 @@ +; The default interrupt handlers. +; from 20 - 31 are reserved vectors. +; below are the custom ones! + +section .text +align 4 + +; Port helpers: +global outb +outb: + mov eax, [esp + 8] + mov edx, [esp + 4] + out dx, al + ret + +global inb +inb: + xor eax, eax + mov edx, [esp + 4] + in al, dx + ret + +; Helper functions: +global enableinterrupts +enableinterrupts: + sti + ret + +global halt +halt: + cli + hlt + +global loadIDT +loadIDT: + ret + +; Define macro with two arguments: +%macro INTX 2 +global %1 +%1: + ; Do some saving: +extern %2 + call %2 + ; Do restoration + iret + +%endmacro + +; Exception handlers: +INTX INTDEF, INTDEF_handler +INTX INT0, INT0handler +INTX INT1, INT1handler +INTX INT2, INT2handler +INTX INT3, INT3handler +INTX INT4, INT4handler +INTX INT5, INT5handler +INTX INT6, INT6handler +INTX INT7, INT7handler +INTX INT8, INT8handler +INTX INT9, INT9handler +INTX INT10, INT10handler +INTX INT11, INT11handler +INTX INT12, INT12handler +INTX INT13, INT13handler +INTX INT14, INT14handler +INTX INT15, INT15handler +INTX INT16, INT16handler +INTX INT17, INT17handler +INTX INT18, INT18handler +INTX INT19, INT19handler + +INTX INT32, INT32handler +INTX INT33, INT33handler +INTX INT34, INT34handler +
--- a/cos/kernel/goto64.asm Tue Nov 15 07:35:00 2011 +0100 +++ b/cos/kernel/goto64.asm Fri Nov 18 14:41:53 2011 +0100 @@ -145,7 +145,7 @@ stackEnd: einde: -XCHG BX, BX ; bochs breakpoint +# XCHG BX, BX ; bochs breakpoint # Call kernel: extern kmain
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/kernel/handlers.c Fri Nov 18 14:41:53 2011 +0100 @@ -0,0 +1,296 @@ +#include "kernel.h" + +void panic(char *msg) { + printf("Kernel panic: "); + printf(msg); + halt(); +} + +// Assembler wrapper prototypes: +void INTDEF(void); +void INT0(void); +void INT1(void); +void INT2(void); +void INT3(void); +void INT4(void); +void INT5(void); +void INT6(void); +void INT7(void); +void INT8(void); +void INT9(void); +void INT10(void); +void INT11(void); +void INT12(void); +void INT13(void); +void INT14(void); +void INT15(void); +void INT16(void); +void INT17(void); +void INT18(void); +void INT19(void); +// Remapped handlers: +void INT32(void); +void INT33(void); +void INT34(void); + +// THE interrupt descriptor table: +static struct IDT_entry idt[256]; + +void setIDTentry(int num, void (*handler)()) +{ + // Fill one entry with IDT info: + uint64_t offset; + unsigned short selector = 0x8; // Code selector + unsigned char type = 0x8E; // 32 bits interrupt gate. Thingy is present + + offset = (uint64_t) handler; + + idt[num].b[0] = offset & 0xFF; + idt[num].b[1] = (offset >> 8) & 0xFF; + idt[num].b[2] = selector & 0xFF; + idt[num].b[3] = (selector >> 8) & 0xFF; + idt[num].b[4] = 0; // reserved + idt[num].b[5] = type; + idt[num].b[6] = (offset >> 16) & 0xFF; + idt[num].b[7] = (offset >> 24) & 0xFF; +} + +void setupIDT(void) { + int i; + // Fill all vectors with the default handler: + for (i=0; i<256; i++) { + setIDTentry(i, &INTDEF); + } + + // Now set other then default handler: + setIDTentry(0, INT0); + setIDTentry(1, INT1); + setIDTentry(2, INT2); + setIDTentry(3, INT3); + setIDTentry(4, INT4); + setIDTentry(5, INT5); + setIDTentry(6, INT6); + setIDTentry(7, INT7); + setIDTentry(8, INT8); + setIDTentry(9, INT9); + setIDTentry(10, INT10); + setIDTentry(11, INT11); + setIDTentry(12, INT12); + setIDTentry(13, INT13); + setIDTentry(14, INT14); + setIDTentry(15, INT15); + setIDTentry(16, INT16); + setIDTentry(17, INT17); + setIDTentry(18, INT18); + setIDTentry(19, INT19); + /* reserved interrupts: */ + // From int20 - int31 + setIDTentry(32, INT32); + setIDTentry(33, INT33); + setIDTentry(34, INT34); + + // call load IDT asm function: + loadIDT(idt, 256*8-1); + + PICremap(); + enableinterrupts(); +} + +// PIC functions: +void PICremap() { + unsigned char maskmaster, maskslave, pic1, pic2; + pic1 = 0x20; // remapping location master + pic2 = 0x28; + maskmaster = inb(0x21); // master cmd=0x20, data=0x21 + maskslave = inb(0xA1); // slave command=0xA0, data=0xA1 + + outb(0x20, 0x20); // end of init + + outb(0x20, 0x11); // init + ICW1_ICW2 + outb(0xA0, 0x11); // init + ICW1_ICW2 + + outb(0x21, pic1); // ICW2, write offset + outb(0xA1, pic2); // ICW2 + + outb(0x21, 4); // ICW3, write a 4! + outb(0xA1, 2); // ICW3, write a 2! + + outb(0x21, 1); // ICW4, 8086 mode + outb(0xA1, 1); // ICW4 + + outb(0x21, maskmaster); + outb(0xA1, maskslave); +} + +// Interrupt service routines: + +void INT0handler() +{ + printf("INT0 called!\n"); + panic("Unhandled exception!"); +} + +void INT1handler() +{ + printf("INT1 called!\n"); + panic("Unhandled exception!"); +} + +void INT2handler() +{ + printf("INT2 called!\n"); + panic("Unhandled exception!"); +} + +void INT3handler() +{ + printf("INT3 called!\n"); + panic("Unhandled exception!"); +} + +void INT4handler() +{ + printf("INT4 called!\n"); + panic("Unhandled exception!"); +} + +void INT5handler() +{ + printf("INT5 called!\n"); + panic("Unhandled exception!"); +} + +void INT6handler() +{ + printf("INT6 called!\n"); + panic("Unhandled exception!"); +} + +void INT7handler() +{ + printf("INT7 called!\n"); + panic("Unhandled exception!"); +} + +void INT8handler() +{ + printf("INT8 called!\n"); + panic("Unhandled exception!"); +} + +void INT9handler() +{ + printf("INT9 called!\n"); + panic("Unhandled exception!"); +} + +void INT10handler() +{ + printf("INT10 called!\n"); + panic("Unhandled exception!"); +} + +void INT11handler() +{ + printf("INT11 called!\n"); + panic("Unhandled exception!"); +} + +void INT12handler() +{ + printf("INT12 called!\n"); + panic("Unhandled exception!"); +} + +void INT13handler() +{ + printf("INT13 called!\n"); + panic("Unhandled exception!"); +} + +void* getUnusedPage() { + return 0; + +} + +void mappage(uint32_t address) { + uint32_t pageDirIndex = address >> 22; + uint32_t pageTableIndex = (address >> 12) & 0x3FF; + + printf("Allocating page at %d, tableindex=%d\n", pageDirIndex, pageTableIndex); + //uint32_t *pageTable = (uint32_t*)(pageDirectory[pageDirIndex] & 0xFFFFFC00); + + +} + +void INT14handler(unsigned int address) +{ + printf("INT14 called! Page fault for address 0x%x!\n", address); + if ( (address & 0xF0000000) == 0xD0000000 ) { + mappage(address & 0xFFFFF000); + return; + } + + panic("Unhandled exception!"); +} + +void INT15handler() +{ + printf("INT15 called!\n"); + panic("Unhandled exception!"); +} + +void INT16handler() +{ + printf("INT16 called!\n"); + panic("Unhandled exception!"); +} + +void INT17handler() +{ + printf("INT17 called!\n"); + panic("Unhandled exception!"); +} + +void INT18handler() +{ + printf("INT18 called!\n"); + panic("Unhandled exception!"); +} + +void INT19handler() +{ + printf("INT19 called!\n"); + panic("Unhandled exception!"); +} + +// remapped IRQ from master PIC: +void INT32handler() +{ + // System timer. + //printf("INT32 called!\n"); + // called very frequent, what is this? + timerDriverUpdate(); + outb(0x20, 0x20); // EOI to master +} + +void INT33handler() +{ + //printf("INT33 called, key pressed????\n"); + unsigned char scancode = inb(0x60); + //printf("Scancode = 0x%x\n", scancode); + keyboardDriverUpdate(scancode); + outb(0x20, 0x20); // EOI to master +} + +void INT34handler() +{ + printf("INT34 called!\n"); +} + +void INTDEF_handler() +{ + printf("Default int handler called\n"); +} + +
--- a/cos/kernel/kernel.c Tue Nov 15 07:35:00 2011 +0100 +++ b/cos/kernel/kernel.c Fri Nov 18 14:41:53 2011 +0100 @@ -129,6 +129,9 @@ clear_screen(); printf("Welcome!\n"); printf("sizeof(uint32_t)=%u, sizeof(uint64_t)=%u\n", sizeof(uint32_t), sizeof(uint64_t)); + + printf("Enabling interrupts\n"); + setupIDT(); printf("Entering mainloop!\n"); while (1==1)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/kernel/kernel.h Fri Nov 18 14:41:53 2011 +0100 @@ -0,0 +1,121 @@ +#ifndef KERNEL_H +#define KERNEL_H + +// Include common functions, available to all! +#define NULL ((void*)0) + +// Type defs: +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef unsigned short ushort_t; +typedef unsigned char uchar_t; +typedef unsigned int uint_t; +typedef unsigned long ulong_t; +typedef unsigned long long ulonglong_t; +typedef unsigned long off_t; +typedef unsigned long size_t; + +void printf(const char* fmt, ... ); +void memset(void* ptr, uint32_t value, uint32_t num); +void memcpy(void* dst, void* src, uint32_t num); + +struct IDT_entry { + unsigned char b[8]; +}; + +// memory alloc functions: +void* malloc(size_t size); +void free(void* ptr); + +void clear_screen(); +void init_screen(); +void print_string(const char *); + +// For IO ports: +unsigned char inb(unsigned short); +void outb(unsigned short, unsigned char); + +// ASM helper: +int loadIDT(struct IDT_entry *table, unsigned short size); +void halt(void); + +void setupIDT(void); +void PICremap(void); +// Assembler util functions: +void enableinterrupts(void); +void callint49(void); +void doCPUID(int eax, int *ebx, int *ecx, int *edx); + +// Keyboard driver: +void keyboardDriverUpdate(unsigned char scancode); +void timerDriverUpdate(void); + +// Memory functions: +void mappage(uint32_t address); + +int querymode(void); +int getcs(void); +void loadPageTable(void* tableAddress); +void enablePaging(void); + +// Variable argument list things: +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +typedef __builtin_va_list va_list; + +struct multiboot_aout_symbol_table { + uint32_t tabsize; + uint32_t strsize, addr, reserved; +}; + +struct multiboot_info { + uint32_t flags; // Multiboot flags / version + uint32_t mem_lower; // available memory from BIOS + uint32_t mem_upper; + uint32_t boot_device; + uint32_t cmdline; // COmmand line + uint32_t mods_count; + uint32_t mods_addr; + union { + struct multiboot_aout_symbol_table aout_sym; + } u; + + uint32_t mmap_length; + uint32_t mmap_addr; +}; + +struct memory_map { + uint32_t size; + uint32_t baselow, basehigh; + uint32_t lenlow, lenhigh; + uint32_t type; +}; + +typedef struct { + char name[32]; // Name of the console + unsigned char screendata[80*25]; // All chars in the console! +} console_t; + +typedef struct { + uint32_t esp; + uint32_t ss; + uint32_t kstack; + uint32_t ustack; + uint32_t cr3; + + uint32_t number; + uint32_t parent; + uint32_t owner; + uint32_t groups; + uint32_t timetorun; + uint32_t sleep; + uint32_t priority; + uint32_t filehandle; + char naam[32]; + + console_t *console; +} programma_t; + +#endif +
--- a/cos/kernel/snprintf.c Tue Nov 15 07:35:00 2011 +0100 +++ b/cos/kernel/snprintf.c Fri Nov 18 14:41:53 2011 +0100 @@ -3,8 +3,20 @@ */ #include "kernel.h" -#include "stdarg.h" -#include "ctype.h" +/* + * NOTE! This ctype does not handle EOF like the standard C + * library is required to. + */ + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + unsigned char _ctype[] = { _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ @@ -32,6 +44,36 @@ _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) + +#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) +#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) +#define iscntrl(c) ((__ismask(c)&(_C)) != 0) +#define isdigit(c) ((__ismask(c)&(_D)) != 0) +#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) +#define islower(c) ((__ismask(c)&(_L)) != 0) +#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) +#define ispunct(c) ((__ismask(c)&(_P)) != 0) +#define isspace(c) ((__ismask(c)&(_S)) != 0) +#define isupper(c) ((__ismask(c)&(_U)) != 0) +#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + +static inline unsigned char tolower(unsigned char c) +{ + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +static inline unsigned char toupper(unsigned char c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} #define MORE_THAN_YOU_WANT 1<<30 #define MAX_STDOUT_CHARS 255 @@ -86,7 +128,7 @@ break; case 'c': /* single character */ - *b++ = va_arg(pvar, char); + *b++ = 'x'; // TODO: va_arg(pvar, char); l--; break;