diff --git a/include/extras/buf.h b/include/extras/buf.h index 2d17d93..5f68e98 100644 --- a/include/extras/buf.h +++ b/include/extras/buf.h @@ -34,15 +34,16 @@ // enum { - BF_LINE = 1, // Line-buffered - BF_FILE = 1<<1, // Linked to a file - BF_BALLOC = 1<<2, // Buffer structure was malloc'd - BF_SALLOC = 1<<3, // Internal buffer was malloc'd - BF_FONCLOSE = 1<<4, // Flush on close - BF_AUTOSCROLL = 1<<5, // Scroll-down automatically + BF_TERM = 1, // Terminal buffer + BF_LINE = 1<<1, // Line-buffered + BF_FILE = 1<<2, // Linked to a file + BF_BALLOC = 1<<3, // Buffer structure was malloc'd + BF_SALLOC = 1<<4, // Internal buffer was malloc'd + BF_FONCLOSE = 1<<5, // Flush on close + BF_AUTOSCROLL = 1<<6, // Scroll-down automatically - BF_EOF = 1<<6, // End of file reached - BF_ERR = 1<<7, // An error happened + BF_EOF = 1<<7, // End of file reached + BF_ERR = 1<<8, // An error happened }; // @@ -61,7 +62,7 @@ enum typedef struct Buffer_t Buffer_t; // -// For line buffers, the flusher by bputc() is called every '\n' +// For line/terminal buffers, the flusher by bputc() is called every '\n' // For pure buffers, the flusher is called by bputc() after it fills // the buffer (unless flush-on-close is enabled) // @@ -90,7 +91,7 @@ struct Buffer_t BFlusher_t flusher; // See above - // The following parameters are only used in line buf mode + // The following parameters are only used in terminal buf mode int lastLF; // Characters since beginning of line int lineLen; // Line length (for line buffers) @@ -98,14 +99,16 @@ struct Buffer_t // size/(lineLen*nLines) - 1 playback buffers }; -extern Buffer_t *BStdOut, *BStdDbg; +extern Buffer_t *BStdIn, *BStdOut, *BStdDbg; -error_t BCloseBuf(Buffer_t *); -void BFlushOnClose(Buffer_t *); +// For pure buffers only +void BEnableLineBuffering(Buffer_t *); +void BDisaleLineBuffering(Buffer_t *); +// For terminal buffers only +error_t BScrollDownBuf(Buffer_t *); void BEnableAutoScroll(Buffer_t *); void BDisableAutoScroll(Buffer_t *); - // // Buffer creation functions // @@ -116,34 +119,32 @@ void BDisableAutoScroll(Buffer_t *); // If source==NULL, malloc's the buffer // BCloseBuf() handles the de-allocations // +error_t BCloseBuf(Buffer_t *); // Creates a pure buffer of a given size error_t BOpenPureBuf(Buffer_t **pbuf, int mode, size_t size); error_t BOpenPureBufEx(Buffer_t **, char *source, int mode, size_t, BFlusher_t); -// Creates a lined buffer of pbCount*nLines lines each +// Creates a terminal buffer of pbCount*nLines lines each // of lineLen length (pb = playback buffer, for scrolling up) -error_t BOpenLineBuf(Buffer_t **pbuf, int mode, +error_t BOpenTermBuf(Buffer_t **pbuf, int mode, int lineLen, int nLines, int pbCount); -error_t BOpenLineBufEx(Buffer_t **pbuf, char *source, int mode, +error_t BOpenTermBufEx(Buffer_t **pbuf, char *source, int mode, int lineLen, int nLines, int pbCount, BFlusher_t); int BGetFlags(Buffer_t *); int BGetState(Buffer_t *); -int BGetLineLen(Buffer_t *); -void BSetLineLen(Buffer_t *, int); + +error_t BFlushBuf(Buffer_t *); +error_t BPutOnBuf(Buffer_t *, uchar); +error_t BPrintOnBuf(Buffer_t *, const char *fmt, ...); +error_t BPrintOnBufV(Buffer_t *, const char *fmt, va_list); void BLockBuf(Buffer_t *); void BUnlockBuf(Buffer_t *); bool BTrylockBuf(Buffer_t *); -error_t BFlushBuf(Buffer_t *); -error_t BScrollDownBuf(Buffer_t *); -error_t BPutOnBuf(Buffer_t *, uchar); -error_t BPrintOnBuf(Buffer_t *, const char *fmt, ...); -error_t BPrintOnBufV(Buffer_t *, const char *fmt, va_list); - // Internal, non-locking functions; don't use unless you // have a good reason why error_t bputc(Buffer_t *buf, uchar ch); diff --git a/include/kernel/base.h b/include/kernel/base.h index 8516f42..9069a04 100644 --- a/include/kernel/base.h +++ b/include/kernel/base.h @@ -170,6 +170,14 @@ noreturn void KeStartPanic(const char *, ...); #define BUG() XBUG('B') #define BUGON(x) if(x)BUG() +#define __GET_GETRIP() \ +__attribute__((__noinline__)) \ +static ulong __getrip() \ +{ return (size_t)__builtin_return_address(0); } + +#define __PRINT_RIP() \ +DebugLog("%s.RIP=%p\n",__func__,__getrip()) + //----------------------------------------------------------------------------// #endif diff --git a/include/kernel/heap.h b/include/kernel/heap.h index 5b389d6..c711358 100644 --- a/include/kernel/heap.h +++ b/include/kernel/heap.h @@ -32,7 +32,9 @@ //----------------------------------------------------------------------------// // Address of the heap -void *_heap_start; +extern void *_heap_start; +extern void *_heap_end; +extern size_t _heap_max; void MmInitHeap(void); diff --git a/kaleid/kernel/init/init.c b/kaleid/kernel/init/init.c index 4e88cd9..d7cfa28 100644 --- a/kaleid/kernel/init/init.c +++ b/kaleid/kernel/init/init.c @@ -75,22 +75,22 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg) // Several inits MmInitHeap(); - PsInitSched(); + //PsInitSched(); // Interrupts launching IdtSetup(); KeEnableIRQs(); - // Drivers enabling IoEnableRtc(); IoEnableKeyb(); + IoGetRtcTimeChar(); IoPrintRtcTime(); - - IoDoStarWars(); + // IoDoStarWars(); KernLog("Goodbye at %s\n", IoGetRtcTimeChar()); + // End this machine's suffering - BStdOut->flusher(BStdOut); + BFlushBuf(BStdOut); KeCrashSystem(); } diff --git a/kaleid/kernel/io/keyb.c b/kaleid/kernel/io/keyb.c index 475859b..7a3a2b4 100644 --- a/kaleid/kernel/io/keyb.c +++ b/kaleid/kernel/io/keyb.c @@ -31,7 +31,7 @@ char ScanCodes[100] = { 0 }; void KeybPrint(char code) { if (code) { - bprintf(BStdOut, "%c", ScanCodes[(int)code]); + bputc(BStdOut, ScanCodes[(int)code]); //bprintf(BStdOut, "%x ", code); BStdOut->flusher(BStdOut); } @@ -51,7 +51,8 @@ void ScanCodesInit(void) ScanCodes[0x0B] = '0'; ScanCodes[0x0C] = ' '; ScanCodes[0x0D] = '+'; - ScanCodes[0x0E] = ' '; + ScanCodes[0x0E] = 0x8; + ScanCodes[0x0F] = '\t'; ScanCodes[0x10] = 'a'; ScanCodes[0x11] = 'z'; @@ -113,13 +114,29 @@ void KeybHandler(ISRFrame_t *regs) IoSendEOItoPIC(0x21); } +void IoCreateInputBuffer(void) +{ + error_t rc; + + rc = BOpenPureBuf(&BStdIn, BS_RDWR, 4 * KB); + + if (rc) KeStartPanic("Couldn't create BStdIn"); + + BEnableLineBuffering(BStdIn); +} + void IoEnableKeyb(void) { ulong flags = KePauseIRQs(); + IdtRegisterIsr(KeybHandler, 0x21); char readedInterruptConfig = IoReadByteFromPort(0x21); IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig); + KeRestoreIRQs(flags); + IoEnableNMI(); ScanCodesInit(); + + IoCreateInputBuffer(); } diff --git a/kaleid/kernel/io/rtc.c b/kaleid/kernel/io/rtc.c index dbf7cb7..c28a3fa 100644 --- a/kaleid/kernel/io/rtc.c +++ b/kaleid/kernel/io/rtc.c @@ -164,7 +164,8 @@ void IoPrintRtcTime(void) char* IoGetRtcTimeChar(void) { Time_t *RtcTime = IoGetRtcTime(); - sprintf(IoTimeChar, "%hhd/%hhd/%hd ; %hhd:%hhd:%hhd", + snprintf(IoTimeChar, sizeof(IoTimeChar), + "%02d/%02d/%02d ; %02d:%02d:%02d", RtcTime->day, RtcTime->month, RtcTime->year + RtcTime->century*100, diff --git a/kaleid/kernel/io/vga.c b/kaleid/kernel/io/vga.c index 788bccd..d5e9683 100644 --- a/kaleid/kernel/io/vga.c +++ b/kaleid/kernel/io/vga.c @@ -90,7 +90,7 @@ error_t IoInitVGABuffer(void) BStdOut = &bvgabufstruct; - BOpenLineBufEx(&BStdOut, + BOpenTermBufEx(&BStdOut, bvgabufsrc, BS_WRONLY, BtVideoInfo.framebufferWidth, BtVideoInfo.framebufferHeight, diff --git a/kaleid/kernel/mm/heap.c b/kaleid/kernel/mm/heap.c index b36c7da..58da950 100644 --- a/kaleid/kernel/mm/heap.c +++ b/kaleid/kernel/mm/heap.c @@ -26,11 +26,14 @@ #include #include -// Least address out of the heap -static void *_heap_end; +// Start address of the heap +void *_heap_start; + +// End of the heap +/*static*/ void *_heap_end; // Maximal value of the heap -static size_t _heap_max; +/*static*/ size_t _heap_max; // Lock NOT used internally, but used by KalAllocMemory() & co. static Lock_t _heap_lock = ExINITLOCK(KLOCK_SPINLOCK); @@ -114,6 +117,7 @@ error_t MmGrowHeap(size_t req) assert(req % alignof(QWORD) == 0); if ((size_t)_heap_end + req > (size_t)_heap_start + _heap_max) { + assert(!"Can't extend heap that much"); return ENOMEM; } @@ -130,6 +134,7 @@ error_t MmShrinkHeap(size_t req) assert(req % alignof(QWORD) == 0); if (req > (size_t)_heap_end - (size_t)_heap_start) { + assert(!"Can't shrink heap that much"); return EADDRINUSE; } diff --git a/kaleid/kernel/mm/malloc.c b/kaleid/kernel/mm/malloc.c index c6b5730..a00348a 100644 --- a/kaleid/kernel/mm/malloc.c +++ b/kaleid/kernel/mm/malloc.c @@ -34,7 +34,6 @@ error_t KalAllocMemoryEx(void **ptr, size_t req, int flags, size_t align) { error_t rc; size_t brk; - extern void *_heap_start; if (align == 0) align = M_DEFAULT_ALIGNMENT; diff --git a/kaleid/kernel/mm/map.c b/kaleid/kernel/mm/map.c index c876a50..33b816f 100644 --- a/kaleid/kernel/mm/map.c +++ b/kaleid/kernel/mm/map.c @@ -58,7 +58,7 @@ static error_t InitMemoryMap(void) if ((BtMemoryInfo.upMemory / (MB/KB)) <= MINIMUM_RAM_SIZE) return ENOMEM; -// Ok then we can work ------------------------------------------------------ // + // Ok then we can work // the memory map provided by GRUB via the BIOS currentEntry = (multiboot_memory_map_t*)BtMemoryInfo.mapAddr; diff --git a/kaleid/libbuf/bgetc.c b/kaleid/libbuf/bgetc.c new file mode 100644 index 0000000..e69de29 diff --git a/kaleid/libbuf/bprint.c b/kaleid/libbuf/bprint.c index 2fabdcb..1127de2 100644 --- a/kaleid/libbuf/bprint.c +++ b/kaleid/libbuf/bprint.c @@ -392,7 +392,7 @@ error_t vbprintf(Buffer_t *buf, const char *fmt, va_list ap) // Carry on to next modifier } - // Assert rc for debugging purposes + // Assert !rc for debugging purposes assert(!rc); return rc; diff --git a/kaleid/libbuf/bputc.c b/kaleid/libbuf/bputc.c index ba2ce00..42d6e26 100644 --- a/kaleid/libbuf/bputc.c +++ b/kaleid/libbuf/bputc.c @@ -34,7 +34,6 @@ error_t BPutOnBuf(Buffer_t *buf, uchar ch) assert(buf && buf->initDone == INITOK); if (!buf) return EINVAL; - if (buf->flags & (BF_EOF|BF_ERR)) return EENDF; if (buf->state != BS_RDWR && buf->state != BS_WRONLY) { return EBADF; } @@ -52,10 +51,12 @@ error_t bputc(Buffer_t *buf, uchar ch) { error_t rc = EOK; - // Implements playback / scrolling up when line buffering + if (buf->flags & (BF_EOF|BF_ERR)) return EENDF; + + // Implements playback / scrolling up when terminal buffering // Note that '\n', '\r' and '\t' can never occur in the buffer // That should change; there should be a flag for it - if (buf->flags & BF_LINE) { + if (buf->flags & BF_TERM) { // Deal with line feeds by filling the rest of the line with spaces // We need a field for choosing a different filler, e.g. '\0' @@ -93,7 +94,21 @@ error_t bputc(Buffer_t *buf, uchar ch) while (buf->lastLF % 4 > 0) { rc = bputc(buf, ' '); } - if (rc > 0) return rc; + } + + // Backspace + else if (ch == 8) { + if (buf->wp > buf->buf) { + buf->wp--; + rc = bputc(buf, ' '); + if (!rc) buf->wp--; + } + } + + // DEL character + else if (ch == 127) { + rc = bputc(buf, ' '); + if (!rc) buf->wp--; } // Just a regular character @@ -118,7 +133,7 @@ error_t bputc(Buffer_t *buf, uchar ch) } } - // Not line-buffering + // Not a terminal buffer else { if (buf->wp == buf->buf + buf->size) { buf->flags |= BF_EOF; @@ -127,11 +142,22 @@ error_t bputc(Buffer_t *buf, uchar ch) *buf->wp++ = ch; - if (buf->wp == buf->buf + buf->size && !(buf->flags&BF_FONCLOSE)) { - buf->flusher(buf); + if (buf->wp == buf->buf + buf->size) { + if (!(buf->flags & (BF_LINE|BF_FONCLOSE))) { + if (buf->flusher) buf->flusher(buf); + } + } + + // Line-buffering + if (ch == '\n' && buf->flags & BF_LINE) { + if (buf->flusher) buf->flusher(buf); } } - return EOK; + if (rc != EOK) { + // buf->flags |= BF_ERR; + } + + return rc; } diff --git a/kaleid/libbuf/bscroll.c b/kaleid/libbuf/bscroll.c index a9b7a15..083bc49 100644 --- a/kaleid/libbuf/bscroll.c +++ b/kaleid/libbuf/bscroll.c @@ -34,6 +34,7 @@ error_t BScrollDownBuf(Buffer_t *buf) assert(buf && buf->initDone == INITOK); if (!buf) return EINVAL; + if (!(buf->flags & BF_TERM)) return EBADF; if (buf->flags & (BF_EOF|BF_ERR)) return EENDF; if (buf->state != BS_RDWR && buf->state != BS_WRONLY) { return EBADF; diff --git a/kaleid/libbuf/buf.c b/kaleid/libbuf/buf.c index 8af53eb..2e10b07 100644 --- a/kaleid/libbuf/buf.c +++ b/kaleid/libbuf/buf.c @@ -26,13 +26,25 @@ #include #include -Buffer_t *BStdOut, *BStdDbg; +#include + +Buffer_t *BStdIn, *BStdOut, *BStdDbg; // Straightforward functions int BGetFlags(Buffer_t *buf) { return buf->flags; } int BGetState(Buffer_t *buf) { return buf->state; } -int BGetLineLen(Buffer_t *buf) { return buf->lineLen; } -void BSetLineLen(Buffer_t *buf, int len) { buf->lineLen = len; } + +void BEnableLineBuffering(Buffer_t *buf) +{ + assert(buf && !(buf->flags & BF_TERM)); + buf->flags |= BF_LINE; +} + +void BDisaleLineBuffering(Buffer_t *buf) +{ + assert(buf && !(buf->flags & BF_TERM)); + buf->flags &= ~BF_LINE; +} void BLockBuf(Buffer_t *buf) { @@ -43,8 +55,6 @@ void BLockBuf(Buffer_t *buf) void BUnlockBuf(Buffer_t *buf) { ExReleaseLock(&buf->lock); } bool BTrylockBuf(Buffer_t *buf) { return ExAttemptLock(&buf->lock); } -void BFlushOnClose(Buffer_t *buf) { buf->flags |= BF_FONCLOSE; } - // // Closes a buffer, not flushing unless the proper flag is set // @@ -129,16 +139,16 @@ error_t BOpenPureBufEx(Buffer_t **pbuf, char *source, int mode, size_t size, } // -// Creates a line buffer of (nLines + pbCount*nLines) lines each +// Creates a terminal buffer of (nLines + pbCount*nLines) lines each // of lineLen length (pb = playback buffer, for scrolling up) // -error_t BOpenLineBuf(Buffer_t **pbuf, int mode, +error_t BOpenTermBuf(Buffer_t **pbuf, int mode, int lineLen, int nLines, int pbCount) { - return BOpenLineBufEx(pbuf, NULL, mode, lineLen, nLines, pbCount, NULL); + return BOpenTermBufEx(pbuf, NULL, mode, lineLen, nLines, pbCount, NULL); } -error_t BOpenLineBufEx(Buffer_t **pbuf, char *source, int mode, +error_t BOpenTermBufEx(Buffer_t **pbuf, char *source, int mode, int lineLen, int nLines, int pbCount, BFlusher_t flusher) { error_t rc; @@ -152,7 +162,7 @@ error_t BOpenLineBufEx(Buffer_t **pbuf, char *source, int mode, (*pbuf)->lastLF = 0; (*pbuf)->nLines = nLines; (*pbuf)->lineLen = lineLen; - (*pbuf)->flags |= BF_LINE; + (*pbuf)->flags |= BF_TERM; } return rc; diff --git a/kaleid/libc/mem.c b/kaleid/libc/mem.c index 836d9f7..67b740f 100644 --- a/kaleid/libc/mem.c +++ b/kaleid/libc/mem.c @@ -25,6 +25,8 @@ #include #include +#include + /* DO NOT compile with strict aliasing on */ //------------------------------------------// @@ -178,7 +180,7 @@ void *memcpy(void *restrict dst, const void *restrict src, size_t bytes) const ulong *usrc = (const ulong *)src; ulong *udst = (ulong *)dst; - assert("Don't use this, use memmove()"); + assert(!"Don't use this, use memmove()"); assert((dst + bytes < src || src + bytes < dst) && "memcpy() overlap; use memmove()"); if unlikely (bytes == 0) return dst; diff --git a/kaleid/libc/sprintf.c b/kaleid/libc/sprintf.c index f7f3882..85dd29e 100644 --- a/kaleid/libc/sprintf.c +++ b/kaleid/libc/sprintf.c @@ -22,11 +22,20 @@ // along with OS/K. If not, see . // //----------------------------------------------------------------------------// -// -// TODO integer modifiers -// +#include -#include +// +// XXX +// For now vsnprintf won't support n > 4096 +// vsnprintf() is implemented using the libbuf, which +// does not support dynamically sized buffers (yet) +// (because we need realloc() for that, and we don't have it yet) +// So for now we have to create a buffer of size n which is allocated +// hard, with no paging etc. +// Once libbuf is supports dynamic buffers, the only changes necessary +// will be to change the value below to and add a line to vsnprintf() +// +#define VSNPRINTF_MAX 512 // // Format str according to fmt using ellipsed arguments @@ -36,8 +45,10 @@ size_t sprintf(char *str, const char *fmt, ...) int ret; va_list ap; + assert(!"sprintf() is deprecated, used snprintf() for more safety"); + va_start(ap, fmt); - ret = vsnprintf(str, SIZE_T_MAX, fmt, ap); + ret = vsnprintf(str, VSNPRINTF_MAX, fmt, ap); va_end(ap); return ret; @@ -45,7 +56,7 @@ size_t sprintf(char *str, const char *fmt, ...) size_t vsprintf(char *str, const char *fmt, va_list ap) { - return vsnprintf(str, SIZE_T_MAX, fmt, ap); + return vsnprintf(str, VSNPRINTF_MAX, fmt, ap); } // @@ -64,6 +75,57 @@ size_t snprintf(char *str, size_t n, const char *fmt, ...) return ret; } +__GET_GETRIP(); +size_t vsnprintf(char *str, size_t n, const char *fmt, va_list ap) +{ + size_t ret; + error_t rc; + Buffer_t *buf; + + assert(str && fmt); + + if (n == 0) return 0; + if (n > VSNPRINTF_MAX) { + assert(!"Not yet..."); + goto fail; + } + + // n-1 to leave place for the '\0' + if (BOpenPureBuf(&buf, BS_WRONLY, n-1) != EOK) { + goto fail; + } + rc = vbprintf(buf, fmt, ap); + + // We don't mind EOFs, just just return how much was successfully written + if (rc != EOK && !(rc == EENDF && !(buf->flags & BF_EOF))) { + goto fail; + } + + ret = (size_t)buf->wp - (size_t)buf->buf; + + if (ret > 0) { + // To be changed to memcpy() + memmove(str, (char *)buf->buf, ret); + } + + str[ret++] = 0; + assert(ret <= n); +//109e38 101c63 + + BCloseBuf(buf); + return ret; + +fail: + assert(!"vsnprintf() failure"); + *str = 0; + return 0; +} + +// +// Old code +// +#if 0 + // Size of the buffer is for convertions #define CONVBUF 64 @@ -242,3 +304,5 @@ size_t vsnprintf(char *str, size_t n, const char *fmt, va_list ap) return ret + 1; } +#endif +