2017-03-10 4 views
1

ich einen Kernel folgende James M Tutorials zu schreiben, und vor kurzem habe ich ein Tastaturtreiber (von bkerndev Tutorial), um eine einfache Schale zu implementieren. Der Tastaturtreiber funktionierte bisher gut, bis ich eine Möglichkeit gefunden habe, eine Eingabezeile vom Benutzer zu identifizieren. Es schreibt im Grunde nur die Eingabezeile in ein Array als eine Zeichenfolge, die dann als die 'Eingabe'-Variable in der Datei' kernel.c 'verwendet wird. Allerdings, wenn ich den Code zu kompilieren bekomme ich folgende Fehler von dem Linker:Linker Fehler: undefined reference to `USER_INPUT‘

keyboard.c:(.text+0x8c): undefined reference to `user_input' 

Die Referenz wird definiert in der Datei ‚kernel.h‘.

keyboard.c

#include <kstdio.h> 
#include <isr.h> 
#include <keyboard.h> 
#include <kernel.h> 

u32int shiftKey; 
static char letter; 
static char upLetter; 

static char key_buffer[256]; // The buffer line 

#define RSHIFT 0x80 - 42 
#define LSHIFT 0x80 - 54 
#define ENTER  0x1C 
#define BACKSPACE 0x0E 

// kbdus is the scancode tables for English US 
unsigned char kbdus[128] = 
{ 
    0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ 
    '9', '0', '-', '=', '\b', /* Backspace */ 
    '\t',   /* Tab */ 
    'q', 'w', 'e', 'r', /* 19 */ 
    't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ 
    0,   /* 29 - Control */ 
    'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */ 
'\'', '`', 0,  /* Left shift */ 
'\\', 'z', 'x', 'c', 'v', 'b', 'n',   /* 49 */ 
    'm', ',', '.', '/', 0,    /* Right shift */ 
    '*', 
    0, /* Alt */ 
    ' ', /* Space bar */ 
    0, /* Caps lock */ 
    0, /* 59 - F1 key ... > */ 
    0, 0, 0, 0, 0, 0, 0, 0, 
    0, /* < ... F10 */ 
    0, /* 69 - Num lock*/ 
    0, /* Scroll Lock */ 
    0, /* Home key */ 
    0, /* Up Arrow */ 
    0, /* Page Up */ 
    '-', 
    0, /* Left Arrow */ 
    0, 
    0, /* Right Arrow */ 
    '+', 
    0, /* 79 - End key*/ 
    0, /* Down Arrow */ 
    0, /* Page Down */ 
    0, /* Insert Key */ 
    0, /* Delete Key */ 
    0, 0, 0, 
    0, /* F11 Key */ 
    0, /* F12 Key */ 
    0, /* All other keys are undefined */ 
}; 

unsigned char upkbdus[128] = 
{ 
    0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */ 
    '(', ')', '_', '+', '\b', /* Backspace */ 
    '\t',   /* Tab */ 
    'Q', 'W', 'E', 'R', /* 19 */ 
    'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */ 
    0,   /* 29 - Control */ 
    'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */ 
'\'', '`', 0,  /* Left shift */ 
'\\', 'Z', 'X', 'C', 'V', 'B', 'N',   /* 49 */ 
    'M', ',', '.', '/', 0,    /* Right shift */ 
    '*', 
    0, /* Alt */ 
    ' ', /* Space bar */ 
    0, /* Caps lock */ 
    0, /* 59 - F1 key ... > */ 
    0, 0, 0, 0, 0, 0, 0, 0, 
    0, /* < ... F10 */ 
    0, /* 69 - Num lock*/ 
    0, /* Scroll Lock */ 
    0, /* Home key */ 
    0, /* Up Arrow */ 
    0, /* Page Up */ 
    '-', 
    0, /* Left Arrow */ 
    0, 
    0, /* Right Arrow */ 
    '+', 
    0, /* 79 - End key*/ 
    0, /* Down Arrow */ 
    0, /* Page Down */ 
    0, /* Insert Key */ 
    0, /* Delete Key */ 
    0, 0, 0, 
    0, /* F11 Key */ 
    0, /* F12 Key */ 
    0, /* All other keys are undefined */ 
};    

/* Handles the keyboard interrupt */ 
void keyboard_handler(struct regs *r) 
{ 
    unsigned char scancode; 

    /* Read from the keyboard's data buffer */ 
    scancode = inb(0x60); 

    /* If the top bit of the byte we read from the keyboard is 
    * set, that means that a key has just been released */ 
    if (scancode & 0x80) 
    { 
     if (scancode == LSHIFT || scancode == RSHIFT) { 
      shiftKey = 1; 
     } 
     else { 
      shiftKey = 0; 
     } 
    } 
    else 
    { 
     letter = kbdus[scancode]; 
     upLetter = upkbdus[scancode]; 

     /* Here, a key was just pressed. Please note that if you 
     * hold a key down, you will get repeated key press 
     * interrupts. */ 

     /* Just to show you how this works, we simply translate 
     * the keyboard scancode into an ASCII value, and then 
     * display it to the screen. You can get creative and 
     * use some flags to see if a shift is pressed and use a 
     * different layout, or you can add another 128 entries 
     * to the above layout to correspond to 'shift' being 
     * held. If shift is held using the larger lookup table, 
     * you would add 128 to the scancode when you look for it */ 
     if (scancode == BACKSPACE) { 
     backspace(key_buffer); 
    } else if (scancode == ENTER) { 
     user_input(key_buffer); 
     kprintf("\n"); 
     key_buffer[0] = '\0'; 
    } else { 
     /* Remember that kprint only accepts char[] */ 
     char str[2] = {letter, '\0'}; 
     append(key_buffer, letter); 
     kprintf(str); 
    } 


     /* if (shiftKey == 0) { 
      kputc(letter); 
     } 
     else if (shiftKey == 1) { 
      kputc(upLetter); 
     } */ 
    } 
} 

void keyboard_install() { 
    register_interrupt_handler(IRQ1, &keyboard_handler); 
} 

keyboard.h

#ifndef KEYBOARD_H 
#define KEYBOARD_H 

void keyboard_install(); 

#endif 

kernel.h

#ifndef KERNEL_H 
#define KERNEL_H 

#include <keyboard.h> 

void user_input(char *input); 

#endif 

Makefi le

# Makefile for Sierra Kernel 
# The C and C++ rules are already setup by default. 
# The only one that needs changing is the assembler 
# rule, as we use nasm instead of GNU as. 
DESTDIR?= 
INCLUDEDIR?=include 
PREFIX?=/usr/local 
EXEC_PREFIX?=$(PREFIX) 
BOOTDIR?=$(EXEC_PREFIX)/boot 

export AR=/Users/development/opt/cross/bin/i386-elf-ar 
export AS=/Users/development/opt/cross/bin/i386-elf-as 
export CC=/Users/development/opt/cross/bin/i386-elf-gcc 
export GDB=/Users/development/opt/cross/bin/i386-elf-gdb 

CFLAGS=-nostdlib -nostdinc -fno-builtin -I include 
LDFLAGS=-Tlink.ld 
ASFLAGS=-felf 

SOURCES=boot/boot.o drivers/halt.o drivers/kstdio/screen.o drivers/kstdio/io.o kernel/sierra/kernel.o \ 
       kernel/tables/gdt.o kernel/tables/tables.o kernel/tables/isr.o kernel/timer.o kernel/tables/inter.o \ 
       drivers/keyboard.o 

all: $(SOURCES) link 

clean: 
    rm -rf boot/*.o drivers/*.o drivers/kstdio/*.o kernel/sierra/*.o kernel/tables/*.o \ 
    *.o kernel/*.o *.kernel 

link: 
    /Users/development/opt/cross/i386-elf/bin/ld $(LDFLAGS) -o sierra.kernel $(SOURCES) 

.s.o: 
    nasm $(ASFLAGS) $< 

install: install-headers install-kernel 

install-headers: 
    mkdir -p $(DESTDIR)$(INCLUDEDIR) 
    cp -R --preserve=timestamps include/. $(DESTDIR)$(INCLUDEDIR)/. 

install-kernel: 
    mkdir -p $(DESTDIR)$(BOOTDIR) 
    cp kernel $(DESTDIR)$(BOOTDIR) 

image: 
    ./update_image.sh 

run: 
    qemu-system-i386 -fda system.img 

bundle: 
    make clean 
    make 
    make image 
    make run 

mac: 
    make clean 
    make 

Das gesamte Projekt Quelle ist hier verfügbar: https://github.com/sofferjacob/Sierra-Kernel/tree/testing.

Danke für die Hilfe.

Btw Ich benutze eine Cross-Compile-Toolchain in Ubuntu 16.10 (manchmal benutze ich die gleiche Toolchain in MacOS 10.12, aber es ist in der Regel Ubuntu), um den Kernel zu kompilieren.

+1

Sie * declare * 'user_input' Funktion in Header-Datei, aber ** definiert nie ** es. Deshalb erhalten Sie den Fehler vom Linker. – Tsyvarev

+0

Es ist definiert in [kernel.c] (https://github.com/sofferjacob/Sierra-Kernel/blob/testing/kernel/sierra/kernel.c) –

+0

Sie zeigt nicht diese Quelle in der Frage Post. Wenn Sie über [kernel/sierra/kernel.c] (https://github.com/offerjacob/Sierra-Kernel/blob/testing/kernel/sierra/kernel.c) sprechen, definiert es 'user_input' als ** verschachtelt Funktion **, so dass es außerhalb von 'main()' nicht zugänglich ist. – Tsyvarev

Antwort

0

Diese Änderung kernel.c es gelöst:

#include <kstdio.h> 
#include <tables.h> 
#include <timer.h> 
#include <keyboard.h> 
#include <keyboard.h> 

extern int is_kernel = 0; 
extern int is_user = 0; 

int kernel_main(struct multiboot *mboot_ptr, u32int initial_stack) { 
    is_kernel = 1; 
    is_user = 0; 
    tables_int(); // Initialise all descriptor tables 
    clear_screen(); // Initialise the screen. 
    asm volatile("sti"); 
    timer_init(100); // Initialise timer to 100Hz (This MUST ALWAYS be set to 100 or bad things will happen) 
    kprintf("System sucessfully initialised \n"); 
    show_system_time(); 
    kprintf("Welcome to Sierra Kernel! v.1.0 \n"); 
    keyboard_install(); 
} 

void user_input(char *input) { 
    if (strcmp(input, "test") == 0) { 
    kprintf("TEST \n"); 
    } 
    else { 
    kprintf("ERROR \n"); 
    } 
    kprintf("# "); 
    } 
Verwandte Themen