project(xv6)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -gstabs+ -Werror -fno-omit-frame-pointer -fno-stack-protector")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing -Wall -gstabs -Werror -fno-omit-frame-pointer -fno-stack-protector")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing -Wall -gstabs -Wno-builtin-declaration-mismatch -fno-omit-frame-pointer -fno-stack-protector")
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_C_FLAGS_DEBUG "-O0 -gstabs")
--- /dev/null
+/* See COPYRIGHT for copyright information. */
+
+#ifndef JOS_INC_ERROR_H
+#define JOS_INC_ERROR_H
+
+enum {
+ // Kernel error codes -- keep in sync with list in lib/printfmt.c.
+ E_UNSPECIFIED = 1, // Unspecified or unknown problem
+ E_BAD_ENV, // Environment doesn't exist or otherwise
+ // cannot be used in requested action
+ E_INVAL, // Invalid parameter
+ E_NO_MEM, // Request failed due to memory shortage
+ E_NO_FREE_ENV, // Attempt to create a new environment beyond
+ // the maximum allowed
+ E_FAULT, // Memory fault
+ MAXERROR
+};
+
+#endif // !JOS_INC_ERROR_H */
--- /dev/null
+/* $NetBSD: stdarg.h,v 1.12 1995/12/25 23:15:31 mycroft Exp $ */
+
+#ifndef INCLUDE_STDARG_h_
+#define INCLUDE_STDARG_h_
+
+typedef __builtin_va_list va_list;
+
+#define va_start(ap, last) __builtin_va_start(ap, last)
+
+#define va_arg(ap, type) __builtin_va_arg(ap, type)
+
+#define va_end(ap) __builtin_va_end(ap)
+
+#endif // INCLUDE_STDARG_h_
--- /dev/null
+#ifndef INCLUDE_STDIO_h_
+#define INCLUDE_STDIO_h_
+
+#include "stdarg.h"
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif /* !NULL */
+
+void cputchar(int c);
+int getchar(void);
+int iscons(int fd);
+
+void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...);
+void vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list);
+int snprintf(char *str, int size, const char *fmt, ...);
+int vsnprintf(char *str, int size, const char *fmt, va_list);
+
+int cprintf(const char *fmt, ...);
+int vcprintf(const char *fmt, va_list);
+
+//int printf(const char *fmt, ...);
+int fprintf(int fd, const char *fmt, ...);
+int vfprintf(int fd, const char *fmt, va_list);
+
+char* readline(const char *prompt);
+
+#endif // INCLUDE_STDIO_h_
include_directories(include)
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static -fno-builtin -fno-pic -m32")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static -fno-pic -m32")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m elf_i386")
include(Sources.cmake)
+# Get libgcc...
+execute_process(COMMAND gcc -m32 -print-libgcc-file-name
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ OUTPUT_VARIABLE GCC_LIBRARY
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+message(STATUS "GOT RES ${GCC_RES}")
+message(STATUS "GOT GCCVAR ${GCC_LIBRARY}")
+message(STATUS "GOT ERROR ${GCC_ERROR}")
+
+
+set (git_cmd "git")
+set (git_arg "--version")
+message(STATUS "git cmd: ${git_cmd}")
+execute_process(COMMAND ${git_cmd} ${git_arg}
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ RESULT_VARIABLE git_result
+ OUTPUT_VARIABLE git_ver)
+
+message(STATUS "git ver[${git_result}]: ${git_ver}")
+
add_custom_command(
OUTPUT gen/vectors.S
COMMAND mkdir -p gen && ${CMAKE_CURRENT_SOURCE_DIR}/tools/vectors.pl > gen/vectors.S
add_custom_command(
OUTPUT kernel
- COMMAND ld -m elf_i386 -nostdlib -T ${CMAKE_CURRENT_SOURCE_DIR}/kernel.ld -o kernel ${kernel_OBJECTS} -b binary initcode entryother
+ COMMAND ld -m elf_i386 -T ${CMAKE_CURRENT_SOURCE_DIR}/kernel.ld -o kernel ${kernel_OBJECTS} ${GCC_LIBRARY} -b binary initcode entryother
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/kernel.ld $<TARGET_OBJECTS:kernelobjs> $<TARGET_OBJECTS:vectorobj> ${CMAKE_CURRENT_BINARY_DIR}/initcode ${CMAKE_CURRENT_BINARY_DIR}/entryother)
add_custom_command(
src/picirq.c
src/pipe.c
src/proc.c
+ src/printfmt.c
src/sleeplock.c
src/spinlock.c
src/stab.c
// console.c
void consoleinit(void);
-void cprintf(char*, ...);
void consoleintr(int(*)(void));
void panic(char*) __attribute__((noreturn));
#include <stdatomic.h>
#include "param.h"
+#include "mmu.h"
// Per-CPU state
struct cpu {
#include "asm/x86.h"
+#include "stdio.h"
+#include "stdarg.h"
+
#include "types.h"
#include "defs.h"
#include "param.h"
#include "fs.h"
#include "file.h"
#include "memlayout.h"
+#include "proc.h"
#include "mmu.h"
#include "proc.h"
#include "string.h"
+int uartgetc(void);
+int kbdgetc(void);
+
+void cputchar(int);
+
static void consputc(int);
static int panicked = 0;
} cons;
static void
-printint(int xx, int base, int sign)
+putch(int ch, int *cnt)
{
- static char digits[] = "0123456789abcdef";
- char buf[16];
- int i;
- uint x;
+ cputchar(ch);
+ // This was imported from old cs3210 lab -- it doesn't do anything... so I
+ // removed it
+ // *cnt++;
+}
- if(sign && (sign = xx < 0))
- x = -xx;
- else
- x = xx;
+int
+vcprintf(const char *fmt, va_list ap)
+{
+ int cnt = 0;
- i = 0;
- do{
- buf[i++] = digits[x % base];
- }while((x /= base) != 0);
+ vprintfmt((void*)putch, &cnt, fmt, ap);
+ return cnt;
+}
- if(sign)
- buf[i++] = '-';
+int
+cprintf(const char *fmt, ...)
+{
+ va_list ap;
+ int cnt;
- while(--i >= 0)
- consputc(buf[i]);
-}
-//PAGEBREAK: 50
+ va_start(ap, fmt);
+ cnt = vcprintf(fmt, ap);
+ va_end(ap);
+ return cnt;
+}
+/*
// Print to the console. only understands %d, %x, %p, %s.
void
cprintf(char *fmt, ...)
printint(*argp++, 10, 1);
break;
case 'x':
- case 'X':
case 'p':
printint(*argp++, 16, 0);
break;
if(locking)
release(&cons.lock);
}
-
+*/
void
panic(char *s)
{
cli();
cons.locking = 0;
- // use lapiccpunum so that we can call panic from mycpu()
- cprintf("lapicid %d: panic: ", lapicid());
+ cprintf("cpu with apicid %d: panic: ", lapicid());
cprintf(s);
cprintf("\n");
getcallerpcs(&s, pcs);
#define C(x) ((x)-'@') // Control-x
+
+// return the next input character from the console, or 0 if none waiting
+int
+cons_getc(void)
+{
+ int c;
+
+ // poll for any pending input characters,
+ // so that this function works even when interrupts are disabled
+ // (e.g., when called from the kernel monitor).
+ consoleintr(uartgetc);
+ consoleintr(kbdgetc);
+ acquire(&cons.lock);
+
+ // grab the next character from the input buffer.
+ if (input.r != input.w) {
+ c = input.buf[input.r++];
+ if (input.r == INPUT_BUF)
+ input.r = 0;
+ release(&cons.lock);
+ return c;
+ }
+ release(&cons.lock);
+ return 0;
+}
+
+
+
void
consoleintr(int (*getc)(void))
{
int
consoleread(struct inode *ip, char *dst, int n)
{
- int target;
+ uint target;
int c;
iunlock(ip);
ioapicenable(IRQ_KBD, 0);
}
+void
+cputchar(int c)
+{
+ consputc(c);
+}
+
+int
+getchar(void)
+{
+ int c;
+
+ while ((c = cons_getc()) == 0)
+ /* do nothing */;
+ return c;
+}
+
+int
+iscons(int fdnum)
+{
+ // used by readline
+ return 1;
+}
#include "asm/x86.h"
+#include "stdio.h"
+
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "buf.h"
#include "file.h"
#include "string.h"
+#include "stdio.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
static void itrunc(struct inode*);
#include "types.h"
#include "defs.h"
#include "traps.h"
+#include "stdio.h"
#define IOAPIC 0xFEC00000 // Default physical address of IO APIC
#include "mmu.h"
#include "proc.h"
#include "string.h"
+#include "stdio.h"
static void startothers(void);
static void mpmain(void) __attribute__((noreturn));
--- /dev/null
+// Stripped-down primitive printf-style formatting routines,
+// used in common by printf, sprintf, fprintf, etc.
+// This code is also used by both the kernel and user programs.
+
+#include "types.h"
+#include "stdio.h"
+#include "string.h"
+#include "stdarg.h"
+#include "error.h"
+
+/*
+ * Space or zero padding and a field width are supported for the numeric
+ * formats only.
+ *
+ * The special format %e takes an integer error code
+ * and prints a string describing the error.
+ * The integer may be positive or negative,
+ * so that -E_NO_MEM and E_NO_MEM are equivalent.
+ */
+
+static const char * const error_string[MAXERROR] =
+{
+ [E_UNSPECIFIED] = "unspecified error",
+ [E_BAD_ENV] = "bad environment",
+ [E_INVAL] = "invalid parameter",
+ [E_NO_MEM] = "out of memory",
+ [E_NO_FREE_ENV] = "out of environments",
+ [E_FAULT] = "segmentation fault",
+};
+
+/*
+ * Print a number (base <= 16) in reverse order,
+ * using specified putch function and associated pointer putdat.
+ */
+static void
+printnum(void (*putch)(int, void*), void *putdat,
+ unsigned long long num, unsigned base, int width, int padc)
+{
+ // first recursively print all preceding (more significant) digits
+ if (num >= base)
+ printnum(putch, putdat, num / base, base, width - 1, padc);
+ else {
+ // print any needed pad characters before first digit
+ while (--width > 0)
+ putch(padc, putdat);
+ }
+
+ // then print this (the least significant) digit
+ putch("0123456789abcdef"[num % base], putdat);
+}
+
+// Get an unsigned int of various possible sizes from a varargs list,
+// depending on the lflag parameter.
+static unsigned long long
+getuint(va_list *ap, int lflag)
+{
+ if (lflag >= 2)
+ return va_arg(*ap, unsigned long long);
+ else if (lflag)
+ return va_arg(*ap, unsigned long);
+ else
+ return va_arg(*ap, unsigned int);
+}
+
+// Same as getuint but signed - can't use getuint
+// because of sign extension
+static long long
+getint(va_list *ap, int lflag)
+{
+ if (lflag >= 2)
+ return va_arg(*ap, long long);
+ else if (lflag)
+ return va_arg(*ap, long);
+ else
+ return va_arg(*ap, int);
+}
+
+
+// Main function to format and print a string.
+void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...);
+
+void
+vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
+{
+ register const char *p;
+ register int ch, err;
+ unsigned long long num;
+ int base, lflag, width, precision, altflag;
+ char padc;
+
+ while (1) {
+ while ((ch = *(unsigned char*)fmt++) != '%') {
+ if (ch == '\0')
+ return;
+ putch(ch, putdat);
+ }
+
+ // Process a %-escape sequence
+ padc = ' ';
+ width = -1;
+ precision = -1;
+ lflag = 0;
+ altflag = 0;
+reswitch:
+ switch (ch = *(unsigned char*)fmt++) {
+
+ // flag to pad on the right
+ case '-':
+ padc = '-';
+ goto reswitch;
+
+ // flag to pad with 0's instead of spaces
+ case '0':
+ padc = '0';
+ goto reswitch;
+
+ // width field
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ for (precision = 0;; ++fmt) {
+ precision = precision * 10 + ch - '0';
+ ch = *fmt;
+ if (ch < '0' || ch > '9')
+ break;
+ }
+ goto process_precision;
+
+ case '*':
+ precision = va_arg(ap, int);
+ goto process_precision;
+
+ case '.':
+ if (width < 0)
+ width = 0;
+ goto reswitch;
+
+ case '#':
+ altflag = 1;
+ goto reswitch;
+
+process_precision:
+ if (width < 0)
+ width = precision, precision = -1;
+ goto reswitch;
+
+ // long flag (doubled for long long)
+ case 'l':
+ lflag++;
+ goto reswitch;
+
+ // character
+ case 'c':
+ putch(va_arg(ap, int), putdat);
+ break;
+
+ // error message
+ case 'e':
+ err = va_arg(ap, int);
+ if (err < 0)
+ err = -err;
+ if (err >= MAXERROR || (p = error_string[err]) == NULL)
+ printfmt(putch, putdat, "error %d", err);
+ else
+ printfmt(putch, putdat, "%s", p);
+ break;
+
+ // string
+ case 's':
+ if ((p = va_arg(ap, char *)) == NULL)
+ p = "(null)";
+ if (width > 0 && padc != '-')
+ for (width -= strnlen(p, precision); width > 0; width--)
+ putch(padc, putdat);
+ for (; (ch = *p++) != '\0' && (precision < 0 || --precision >= 0); width--)
+ if (altflag && (ch < ' ' || ch > '~'))
+ putch('?', putdat);
+ else
+ putch(ch, putdat);
+ for (; width > 0; width--)
+ putch(' ', putdat);
+ break;
+
+ // (signed) decimal
+ case 'd':
+ num = getint(&ap, lflag);
+ if ((long long)num < 0) {
+ putch('-', putdat);
+ num = -(long long)num;
+ }
+ base = 10;
+ goto number;
+
+ // unsigned decimal
+ case 'u':
+ num = getuint(&ap, lflag);
+ base = 10;
+ goto number;
+
+ // (unsigned) octal
+ case 'o':
+ // Replace this with your code
+ putch('X', putdat);
+ putch('X', putdat);
+ putch('X', putdat);
+ break;
+
+ // pointer
+ case 'p':
+ putch('0', putdat);
+ putch('x', putdat);
+ num = (unsigned long long)
+ (uint)va_arg(ap, void *);
+ base = 16;
+ goto number;
+
+ // (unsigned) hexadecimal
+ case 'x':
+ num = getuint(&ap, lflag);
+ base = 16;
+number:
+ printnum(putch, putdat, num, base, width, padc);
+ break;
+
+ // escaped '%' character
+ case '%':
+ putch(ch, putdat);
+ break;
+
+ // unrecognized escape sequence - just print it literally
+ default:
+ putch('%', putdat);
+ for (fmt--; fmt[-1] != '%'; fmt--)
+ /* do nothing */;
+ break;
+ }
+ }
+}
+
+void
+printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintfmt(putch, putdat, fmt, ap);
+ va_end(ap);
+}
+
+struct sprintbuf {
+ char *buf;
+ char *ebuf;
+ int cnt;
+};
+
+static void
+sprintputch(int ch, struct sprintbuf *b)
+{
+ b->cnt++;
+ if (b->buf < b->ebuf)
+ *b->buf++ = ch;
+}
+
+int
+vsnprintf(char *buf, int n, const char *fmt, va_list ap)
+{
+ struct sprintbuf b = { buf, buf+n-1, 0 };
+
+ if (buf == NULL || n < 1)
+ return -E_INVAL;
+
+ // print the string to the buffer
+ vprintfmt((void*)sprintputch, &b, fmt, ap);
+
+ // null terminate the buffer
+ *b.buf = '\0';
+
+ return b.cnt;
+}
+
+int
+snprintf(char *buf, int n, const char *fmt, ...)
+{
+ va_list ap;
+ int rc;
+
+ va_start(ap, fmt);
+ rc = vsnprintf(buf, n, fmt, ap);
+ va_end(ap);
+
+ return rc;
+}
+
+
#include "proc.h"
#include "spinlock.h"
#include "string.h"
+#include "stdio.h"
struct {
struct spinlock lock;
-#include "asm/x86.h"
#include "types.h"
+#include "asm/x86.h"
void*
memset(void *dst, int c, uint n)
return os;
}
+ int
+ strnlen(const char *s, uint size)
+ {
+ int n;
+
+ for (n = 0; size > 0 && *s != '\0'; s++, size--)
+ n++;
+ return n;
+ }
+
+
+
// Like strncpy but guaranteed to NUL-terminate.
char*
safestrcpy(char *s, const char *t, int n)
return n;
}
-// Return a pointer to the first occurrence of 'c' in 's',
-// or a pointer to the string-ending null character if the string has no 'c'.
-char *
-strfind(const char *s, char c)
+
+int
+strcmp(const char *p, const char *q)
{
- for (; *s; s++)
- {
- if (*s == c)
- {
- break;
- }
- }
- return (char*)s;
+ while(*p && *p == *q)
+ p++, q++;
+ return (uchar)*p - (uchar)*q;
}
+
+char*
+strchr(const char *s, char c)
+{
+ for(; *s; s++)
+ if(*s == c)
+ return (char*)s;
+ return 0;
+}
+
+// Return a pointer to the first occurrence of 'c' in 's',
+ // or a pointer to the string-ending null character if the string has no 'c'.
+ char *
+ strfind(const char *s, char c)
+ {
+ for (; *s; s++)
+ if (*s == c)
+ break;
+ return (char*)s;
+ }
+
#include "mmu.h"
#include "proc.h"
#include "syscall.h"
+#include "stdio.h"
// User code makes a system call with INT T_SYSCALL.
// System call number in %eax.
#include "mmu.h"
#include "proc.h"
#include "traps.h"
+#include "stdio.h"
#include "spinlock.h"
// Interrupt descriptor table (shared by all CPUs).
outb(COM1+0, c);
}
-static int
+int
uartgetc(void)
{
if(!uart)
#include "proc.h"
#include "elf.h"
#include "string.h"
+#include "stdio.h"
extern char data[]; // defined by kernel.ld
pde_t *kpgdir; // for use in scheduler()