From 2e12c7ca1dc269fd7811fba6c004c663acd54ed1 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 25 Sep 2011 23:58:37 +0200 Subject: [PATCH] add character device to dump all kernel messages --- fs/initrd.c | 12 ++-- include/metalsvm/stdio.h | 6 ++ libkern/stdio.c | 131 +++++++++++++++++++++++++++++++++------ 3 files changed, 126 insertions(+), 23 deletions(-) diff --git a/fs/initrd.c b/fs/initrd.c index 33d1eceb..cc76c994 100644 --- a/fs/initrd.c +++ b/fs/initrd.c @@ -429,19 +429,21 @@ int initrd_init(void) /* create the directory bin and dev */ mkdir_fs(fs_root, "bin"); mkdir_fs(fs_root, "sbin"); - mkdir_fs(fs_root, "var"); tmp = mkdir_fs(fs_root, "dev"); /* create the character device "null" */ null_init(tmp, "null"); - /* create the standart input device "stdin" */ + /* create the standard input device "stdin" */ stdin_init(tmp, "stdin"); - /* create the standart output device "stdout" */ + /* create the standard output device "stdout" */ stdout_init(tmp, "stdout"); - /* create the standart error-output device "stderr" */ + /* create the standard error-output device "stderr" */ stderr_init(tmp, "stderr"); - /* create the standart device "netchar" */ + /* create the standard device "socket" */ socket_init(tmp, "socket"); + /* create the character device "kmessages" */ + tmp = mkdir_fs(fs_root, "var"); + kmsg_init(tmp, "kmessages"); /* For every module.. */ #ifdef CONFIG_MULTIBOOT diff --git a/include/metalsvm/stdio.h b/include/metalsvm/stdio.h index cd5d2a61..dc9e3927 100644 --- a/include/metalsvm/stdio.h +++ b/include/metalsvm/stdio.h @@ -74,6 +74,12 @@ int koutput_init(void); */ int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix, va_list ap); +struct vfs_node; +/** + * Init function to create a character device which represents all kernel messages + */ +int kmsg_init(struct vfs_node* node, const char *name); + /** @brief Set a new foreground color for kprintf and kputchar. * * The color change will affect any procedure using vga_putchar()/vga_puts(). diff --git a/libkern/stdio.c b/libkern/stdio.c index 281fe11d..ac5ab133 100644 --- a/libkern/stdio.c +++ b/libkern/stdio.c @@ -1,22 +1,23 @@ -/* - * Copyright 2010 Stefan Lankes, Chair for Operating Systems, +/* + * Copyright 2010 Stefan Lankes, Chair for Operating Systems, * RWTH Aachen University - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of MetalSVM. + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * This file is part of MetalSVM. */ +#include #include #include #include @@ -43,6 +44,100 @@ static uint32_t early_print = NO_EARLY_PRINT; static atomic_int32_t kmsg_counter = ATOMIC_INIT(0); static unsigned char kmessages[KMSG_SIZE] __attribute__ ((section(".kmsg"))) = {[0 ... KMSG_SIZE-1] = 0x00}; +static ssize_t kmsg_read(fildes_t* file, uint8_t* buffer, size_t size) +{ + size_t start, i = 0; + + if (BUILTIN_EXPECT(!buffer, 0)) + return -EINVAL; + if (BUILTIN_EXPECT(!size, 0)) + return 0; + + if (kmessages[(atomic_int32_read(&kmsg_counter) + 1) % KMSG_SIZE] == 0) + start = 0; + else + start = atomic_int32_read(&kmsg_counter); + + if (((start + file->offset) % KMSG_SIZE) == atomic_int32_read(&kmsg_counter)) + return 0; + + for(i=0; ioffset++) { + buffer[i] = kmessages[(start + file->offset) % KMSG_SIZE]; + if (((start + file->offset) % KMSG_SIZE) == atomic_int32_read(&kmsg_counter)) + return i; + } + + return size; +} + +static int kmsg_open(fildes_t* file, const char *name) +{ + return 0; +} + +static int kmsg_close(fildes_t* file) +{ + return 0; +} + +/* Init Functions */ +int kmsg_init(vfs_node_t * node, const char *name) +{ + uint32_t i, j; + vfs_node_t* new_node; + dir_block_t* blockdir; + dirent_t* dirent; + block_list_t* blist; + + if (BUILTIN_EXPECT(!node || !name, 0)) + return -EINVAL; + + if (BUILTIN_EXPECT(node->type != FS_DIRECTORY, 0)) + return -EINVAL; + + if (finddir_fs(node, name)) + return -EINVAL; + + new_node = kmalloc(sizeof(vfs_node_t)); + if (BUILTIN_EXPECT(!new_node, 0)) + return -ENOMEM; + + memset(new_node, 0x00, sizeof(vfs_node_t)); + new_node->type = FS_CHARDEVICE; + new_node->open = &kmsg_open; + new_node->close = &kmsg_close; + new_node->read = &kmsg_read; + new_node->write = NULL; + spinlock_init(&new_node->lock); + + blist = &node->block_list; + do { + for (i = 0; i < MAX_DATABLOCKS; i++) { + if (blist->data[i]) { + blockdir = (dir_block_t *) blist->data[i]; + for (j = 0; j < MAX_DIRENTRIES; j++) { + dirent = &blockdir->entries[j]; + if (!dirent->vfs_node) { + dirent->vfs_node = new_node; + strncpy(dirent->name, name, MAX_FNAME); + return 0; + } + } + } + } + + if (!blist->next) { + blist->next = (block_list_t *) kmalloc(sizeof(block_list_t)); + if (blist->next) + memset(blist->next, 0x00, sizeof(block_list_t)); + } + } while (blist); + + kfree(new_node, sizeof(vfs_node_t)); + + return -ENOMEM; +} + int koutput_init(void) { #ifdef CONFIG_VGA @@ -60,11 +155,11 @@ int kputchar(int c) kmessages[pos % KMSG_SIZE] = (unsigned char) c; #ifdef CONFIG_VGA if (early_print == VGA_EARLY_PRINT) - vga_putchar(c); -#endif + vga_putchar(c); +#endif #ifdef CONFIG_UART if (early_print == UART_EARLY_PRINT) - uart_putchar(c); + uart_putchar(c); #endif return 1;