ASFLAGS = -Isrc/
CFLAGS = -m32 -march=i386 $(warn) $(opt) $(dbg) -fno-pic -ffreestanding \
-fno-stack-protector -mpreferred-stack-boundary=2 -nostdinc -ffast-math \
- $(inc) $(def)
+ -fno-asynchronous-unwind-tables $(inc) $(def) -MMD
LDFLAGS = -m elf_i386 -nostdlib -T com32.ld -Map test.map
$(bin): $(obj)
$(AS) -o $@ -f elf $(ASFLAGS) $<
%.s: %.c
- $(CC) $(CFLAGS) -masm=intel -g0 -fno-asynchronous-unwind-tables -S $< -o $@
+ $(CC) $(CFLAGS) -masm=intel -S $< -o $@
.PHONY: clean
clean:
/* main program will be moved to 2MB by the loader */
. = 2M;
- main ALIGN(4): AT (_ldr_main_start) {
+ .main ALIGN(4): AT (_ldr_main_start) {
_main_start = .;
* (.startup);
* (.text*);
* (.rodata*);
* (.data*);
+ . = ALIGN(4);
+ }
+ .bss ALIGN(4): AT (_ldr_main_start + SIZEOF(.main)) {
. = ALIGN(4);
_bss_start = .;
* (.bss*);
. = ALIGN(4);
_main_size = . - _main_start;
_mem_start = .;
+
+ /DISCARD/ : {
+ *(.note.GNU-stack);
+ *(.comment);
+ }
}
/* delay for about 1us */
#define iodelay() outp(0x80, 0)
+#define get_ebp(ebp) \
+ asm volatile( \
+ "mov %%ebp, %0\n\t" \
+ : "=g"((uint32_t)(ebp)))
#endif /* ASMOPS_H_ */
#define TICK_FREQ_HZ 250
#define CON_TEXTMODE
-/*#define CON_SERIAL*/
+#define CON_SERIAL
#endif /* PCBOOT_CONFIG_H_ */
static void crtc_cursor(int x, int y);
static void crtc_getcursor(int *x, int *y);
static void crtc_setstart(int y);
+static int crtc_getstart(void);
static inline unsigned char crtc_read(int reg);
static inline void crtc_write(int reg, unsigned char val);
static int curvis;
static int scr_on = 1;
+
int con_init(void)
{
#ifdef CON_SERIAL
cy0 &= 0x1f;
cy1 = crtc_read(CRTC_REG_CUREND) & 0x1f;
+ start_line = crtc_getstart();
crtc_getcursor(&cursor_x, &cursor_y);
con_show_cursor(1);
- crtc_setstart(0);
scr_on = 1;
#endif
crtc_write(CRTC_REG_START_H, addr >> 8);
}
+static int crtc_getstart(void)
+{
+ unsigned int addr;
+
+ addr = crtc_read(CRTC_REG_START_L);
+ addr |= (unsigned int)crtc_read(CRTC_REG_START_H) << 8;
+
+ return addr / NCOLS;
+}
+
static inline unsigned char crtc_read(int reg)
{
outp(CRTC_ADDR, reg);
#define OCW2_EOI (1 << 5)
-void init_pic(void);
static void gate_desc(desc_t *desc, uint16_t sel, uint32_t addr, int dpl, int type);
/* defined in intr_asm.S */
KB_NUM_MUL, KB_LALT, ' ', KB_CAPSLK, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, /* 37 - 44 */
KB_NUMLK, KB_SCRLK, KB_NUM_7, KB_NUM_8, KB_NUM_9, KB_NUM_MINUS, KB_NUM_4, KB_NUM_5, KB_NUM_6, KB_NUM_PLUS, /* 45 - 4e */
KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_0, KB_NUM_DOT, KB_SYSRQ, 0, 0, KB_F11, KB_F12, /* 4d - 58 */
+#if 0
0, 0, 0, 0, 0, 0, 0, /* 59 - 5f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */
+#endif
};
/* extended scancodes, after the 0xe0 prefix */
+#if 0
static int scantbl_set1_ext[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\r', KB_RCTRL, 0, 0, /* 10 - 1f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 - 7f */
};
+#endif
#endif /* KBSCAN_H_ */
num_pressed++;
}
- key = ext ? scantbl_set1_ext[code] : scantbl_set1[code];
- ext = 0;
+ if(!ext) {
+ key = code < 0x59 ? scantbl_set1[code] : 0;
+ } else {
+ switch(code) {
+ case 0x1c: key = '\r'; break;
+ case 0x1d: key = KB_RCTRL; break;
+ //case 0x35: key = KB_NUM_MINUS; break;
+ //case 0x37: key = KB_SYSRQ; break;
+ case 0x38: key = KB_RALT; break;
+ case 0x47: key = KB_HOME; break;
+ case 0x48: key = KB_UP; break;
+ case 0x49: key = KB_PGUP; break;
+ case 0x4b: key = KB_LEFT; break;
+ case 0x4d: key = KB_RIGHT; break;
+ case 0x4f: key = KB_END; break;
+ case 0x50: key = KB_DOWN; break;
+ case 0x51: key = KB_PGDN; break;
+ case 0x52: key = KB_INSERT; break;
+ case 0x53: key = KB_DEL; break;
+ default:
+ key = 0;
+ }
+ ext = 0;
+ }
if(press) {
if(key == KB_DEL && (keystate[KB_LALT] || keystate[KB_RALT]) && (keystate[KB_LCTRL] || keystate[KB_RCTRL])) {
return intern_printf(OUT_SER, 0, 0, fmt, ap);
}
+/*
void perror(const char *s)
{
printf("%s: %s\n", s, strerror(errno));
}
+*/
/* intern_printf provides all the functionality needed by all the printf
* variants.
return dest;
}
-
+/*
static const char *errstr[] = {
"Success",
"Foo",
}
return (char*)errstr[err];
}
+*/
extern boot_mem_map_size
%include 'macros.inc'
+%define CON_SERIAL
[bits 16]
global _start
jmp exit
.notvm86:
+%ifdef CON_SERIAL
call setup_serial
+%endif
call enable_a20
call detect_memory
; ---------------------- memory detection -----------------------
detect_memory:
+ mov si, memdet_detram
+ call printstr
mov si, memdet_e820_msg
call printstr
call detect_mem_e820
mov si, str_fail
call printstr
+ mov si, memdet_detram
+ call printstr
mov si, memdet_e801_msg
call printstr
call detect_mem_e801
mov si, str_fail
call printstr
+ mov si, memdet_detram
+ call printstr
mov esi, memdet_88_msg
call printstr
call detect_mem_88
mov esi, str_fail
call printstr
+ mov si, memdet_detram
+ call printstr
mov esi, memdet_cmos_msg
call printstr
call detect_mem_cmos
str_ok db 'OK',10,0
str_fail db 'failed',10,0
memdet_fail_msg db 'Failed to detect available memory!',10,0
-memdet_e820_msg db 'Detecting RAM (BIOS 15h/0xe820)... ',0
-memdet_e801_msg db 'Detecting RAM (BIOS 15h/0xe801)... ',0
-memdet_88_msg db 'Detecting RAM (BIOS 15h/0x88, max 64mb)... ',0
-memdet_cmos_msg db 'Detecting RAM (CMOS)...',0
+memdet_detram db 'Detecting RAM '
+memdet_e820_msg db '(BIOS 15h/0xe820)... ',0
+memdet_e801_msg db '(BIOS 15h/0xe801)... ',0
+memdet_88_msg db '(BIOS 15h/0x88, max 64mb)... ',0
+memdet_cmos_msg db '(CMOS)...',0
; detect extended memory using BIOS call 15h/e820
detect_mem_e820:
; ----------------------- serial console ------------------------
+%ifdef CON_SERIAL
setup_serial:
; set clock divisor
mov dx, UART_BASE + 3 ; LCTL
jmp ser_printstr
.end: ret
+%endif ; def CON_SERIAL
+
+
printstr:
lodsb
test al, al
cmp al, 10 ; check for line-feed and insert CR before it
jnz .nolf
push ax
+%ifdef CON_SERIAL
mov al, 13
call ser_putchar
+%endif
mov dl, 13
mov ah, 2
int 21h
pop ax
-.nolf: call ser_putchar
+.nolf:
+%ifdef CON_SERIAL
+ call ser_putchar
+%endif
mov ah, 2
mov dl, al
int 21h
jmp printstr
.end: ret
- [bits 32]
-ser_putchar_pmode:
- SER_PUTCHAR
- ret
-
-ser_putstr_pmode:
- lodsb
- test al, al
- jz .end
- cmp al, 10
- jnz .nolf
- push ax
- mov al, 13
- call ser_putchar_pmode
- pop ax
-.nolf: call ser_putchar_pmode
- jmp ser_putstr_pmode
-.end: ret
-
align 4
enterpm dd 0xbad00d ; space for linear address for far jump to pmode
push ax
mov dx, UART_BASE + 5 ; LSTAT
%%wait: in al, dx
- test al, 20h ; TRIG_EMPTY
+ test al, 20h ; TREG_EMPTY
jz %%wait
mov dx, UART_BASE
pop ax
#include "psaux.h"
#include "timer.h"
-extern uint16_t orig_seg;
-
int main(void)
{
init_segm();
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
+#include "intr.h"
#include "asmops.h"
struct all_registers {
for(;;) halt_cpu();
}
+
+void backtrace(void)
+{
+ int lvl = 0;
+ uint32_t *frmptr;
+ int ien = get_intr_flag();
+ disable_intr();
+ get_ebp(frmptr);
+ set_intr_flag(ien);
+
+ while(frmptr) {
+ printf("%d: %p\n", lvl++, (void*)frmptr[1]);
+ frmptr = (uint32_t*)*frmptr;
+ }
+}
#define PANIC_H_
void panic(const char *fmt, ...) __attribute__((noreturn));
+void backtrace(void);
#endif /* PANIC_H_ */
void set_gdt(uint32_t addr, uint16_t limit);
void set_task_reg(uint16_t tss_selector);
+/*
static void dbg_print_gdt(void);
static void print_desc(desc_t *desc);
+*/
/* our global descriptor table */
static desc_t gdt[NUM_SEGMENTS] __attribute__((aligned(8)));
set_gdt((uint32_t)gdt, sizeof gdt - 1);
setup_selectors(selector(SEGM_CODE, 0), selector(SEGM_DATA, 0));
-
- dbg_print_gdt();
}
/* constructs a GDT selector based on index and priviledge level */
TSS_TYPE_BITS; /* XXX busy ? */
desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN;
}
-#endif
static void dbg_print_gdt(void)
{
printf("base:%x lim:%x dpl:%d type:%s %dbit\n", base, limit, dpl,
desc->d[2] & BIT_CODE ? "code" : "data", desc->d[3] & BIT_BIG ? 32 : 16);
}
+#endif
*/
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include "config.h"
#include "serial.h"
#include "asmops.h"
#define COM_FMT_8N1 LCTL_8N1
#define COM_FMT_8N2 LCTL_8N2
+#define INBUF_SIZE 16
+#define BNEXT(x) (((x) + 1) & (INBUF_SIZE - 1))
+#define BEMPTY(b) (b##_ridx == b##_widx)
+
struct serial_port {
int base, intr;
int blocking;
+ int ref;
- char inbuf[256];
+ char inbuf[INBUF_SIZE];
int inbuf_ridx, inbuf_widx;
};
-#define BNEXT(x) (((x) + 1) & 0xff)
-#define BEMPTY(b) (b##_ridx == b##_widx)
static int have_recv(int base);
static void recv_intr();
int ser_open(int pidx, int baud, unsigned int mode)
{
unsigned short div = 115200 / baud;
- int base, intr;
+ int i, fd, base, intr;
unsigned int fmt;
if(pidx < 0 || pidx > 1) {
return -1;
}
- if(ports[pidx].base) {
- printf("ser_open: port %d already open!\n", pidx);
- return -1;
+ for(i=0; i<num_open; i++) {
+ if(ports[i].base == uart_base[pidx]) {
+ /* the port is already open, return the same fd and increment ref */
+ ports[i].ref++;
+ return i;
+ }
}
- memset(ports + pidx, 0, sizeof ports[pidx]);
+
+ fd = num_open++;
+ memset(ports + fd, 0, sizeof ports[pidx]);
base = uart_base[pidx];
intr = uart_irq[pidx];
outp(base + UART_MCTL, MCTL_DTR | MCTL_RTS | MCTL_OUT2);
outp(base + UART_INTR, INTR_RECV);
- ports[pidx].base = base;
- ports[pidx].intr = intr;
- ports[pidx].blocking = 1;
- ++num_open;
- return pidx;
+ ports[fd].base = base;
+ ports[fd].intr = intr;
+ ports[fd].blocking = 1;
+ ports[fd].ref = 1;
+ return fd;
}
void ser_close(int fd)
{
- if(--num_open == 0) {
+ if(!ports[fd].ref) return;
+
+ if(--ports[fd].ref == 0) {
outp(ports[fd].base + UART_INTR, 0);
outp(ports[fd].base + UART_MCTL, 0);
+ ports[fd].base = 0;
}
-
- ports[fd].base = 0;
}
int ser_block(int fd)
char *ser_getline(int fd, char *buf, int bsz)
{
- static char linebuf[512];
static int widx;
+ char linebuf[512];
int i, rd, size, offs;
size = sizeof linebuf - widx;
rep stosd
.nobss:
- mov ebp, 12345678h
+ xor ebp, ebp ; terminate backtraces
call main
cli ; XXX