From 26825756a22412c4521f73b3504b1ae024b798c2 Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Sat, 27 May 2017 21:26:12 +0200
Subject: [PATCH] add option to define uart port via kernel parameters

---
 arch/x86/kernel/entry.asm        |   2 +
 arch/x86/kernel/uart.c           |  26 +++---
 arch/x86/loader/include/ctype.h  | 129 ++++++++++++++++++++++++++++++
 arch/x86/loader/include/limits.h |  87 ++++++++++++++++++++
 arch/x86/loader/include/stddef.h |   8 ++
 arch/x86/loader/include/string.h |   4 +-
 arch/x86/loader/main.c           |   2 +
 arch/x86/loader/strstr.c         |  73 +++++++++++++++++
 arch/x86/loader/strtol.c         | 132 +++++++++++++++++++++++++++++++
 arch/x86/loader/uart.c           |  51 ++++++------
 10 files changed, 474 insertions(+), 40 deletions(-)
 create mode 100644 arch/x86/loader/include/ctype.h
 create mode 100644 arch/x86/loader/include/limits.h
 create mode 100644 arch/x86/loader/strstr.c
 create mode 100644 arch/x86/loader/strtol.c

diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm
index 04f3c43a2..f3b6ce540 100644
--- a/arch/x86/kernel/entry.asm
+++ b/arch/x86/kernel/entry.asm
@@ -69,6 +69,7 @@ align 4
     global hbmem_size
     global uhyve
     global image_size
+    global uartport
     base dq 0
     limit dq 0
     cpu_freq dd 0
@@ -93,6 +94,7 @@ align 4
     hbmem_base dq 0
     hbmem_size dq 0
     uhyve dd 0
+    uartport dq 0
 
 ; Bootstrap page tables are used during the initialization.
 align 4096
diff --git a/arch/x86/kernel/uart.c b/arch/x86/kernel/uart.c
index e96f21920..521685bed 100644
--- a/arch/x86/kernel/uart.c
+++ b/arch/x86/kernel/uart.c
@@ -99,28 +99,28 @@
 
 #define DEFAULT_UART_PORT 	0xc110
 
-static size_t	iobase = 0;
+extern size_t	uartport;
 
 static inline unsigned char read_from_uart(uint32_t off)
 {
 	uint8_t c = 0;
 
-	if (iobase)
-		c = inportb(iobase + off);
+	if (uartport)
+		c = inportb(uartport + off);
 
 	return c;
 }
 
 static inline void write_to_uart(uint32_t off, unsigned char c)
 {
-	if (iobase)
-		outportb(iobase + off, c);
+	if (uartport)
+		outportb(uartport + off, c);
 }
 
 /* Puts a single character on a serial device */
 int uart_putchar(unsigned char c)
 {
-	if (!iobase)
+	if (!uartport)
 		return 0;
 
 	write_to_uart(UART_TX, c);
@@ -133,7 +133,7 @@ int uart_puts(const char *text)
 {
 	size_t i, len = strlen(text);
 
-	if (!iobase)
+	if (!uartport)
 		return 0;
 
 	for (i = 0; i < len; i++)
@@ -188,6 +188,9 @@ int uart_init(void)
 	if (is_uhyve())
 		return 0;
 
+	if (uartport)
+		return uart_config();
+
 	pci_info_t pci_info;
 	uint32_t bar = 0;
 
@@ -205,15 +208,16 @@ int uart_init(void)
 		goto Lsuccess;
 
 	// default value of our QEMU configuration
-	iobase = DEFAULT_UART_PORT;
+	uartport = DEFAULT_UART_PORT;
 
 	// configure uart
-	return uart_config();;
+	return uart_config();
 
 Lsuccess:
-	iobase = pci_info.base[bar];
+	uartport = pci_info.base[bar];
+
 	//irq_install_handler(32+pci_info.irq, uart_handler);
-	kprintf("UART uses io address 0x%x\n", iobase);
+	kprintf("UART uses io address 0x%x\n", uartport);
 
 	// configure uart
 	return uart_config();
diff --git a/arch/x86/loader/include/ctype.h b/arch/x86/loader/include/ctype.h
new file mode 100644
index 000000000..c5aa3915b
--- /dev/null
+++ b/arch/x86/loader/include/ctype.h
@@ -0,0 +1,129 @@
+/****************************************************************************************
+ *
+ * Author: Stefan Lankes
+ *         Chair for Operating Systems, RWTH Aachen University
+ * Date:   24/03/2011
+ *
+ ****************************************************************************************
+ * 
+ * Written by the Chair for Operating Systems, RWTH Aachen University
+ * 
+ * NO Copyright (C) 2010, Stefan Lankes,
+ * consider these trivial functions to be public domain.
+ * 
+ * These functions are distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ */ 
+
+/** 
+ * @author Stefan Lankes
+ * @file include/ctype.h
+ * @brief Functions related to alphanumerical character values
+ *
+ * This file contains functions helping to determine 
+ * the type of alphanumerical character values.
+ */
+
+#ifndef __CTYPE_H_
+#define __CYTPE_H_
+
+/** Returns true if the value of 'c' is an ASCII-charater */
+static inline int isascii(int c) 
+{
+	return (((unsigned char)(c))<=0x7f);
+}
+
+/** Applies an and-operation to 
+ * push the value of 'c' into the ASCII-range */
+static inline int toascii(int c)
+{
+	return (((unsigned char)(c))&0x7f);
+}
+
+/** Returns true if the value of 'c' is the 
+ * space character or a control character */
+static inline int isspace(int c)
+{
+	if (!isascii(c))
+		return 0;
+
+	if (' ' == (unsigned char) c)
+		return 1;
+	if ('\n' == (unsigned char) c)
+		return 1;
+	if ('\r' == (unsigned char) c)
+		return 1;
+	if ('\t' == (unsigned char) c)
+		return 1;
+	if ('\v' == (unsigned char) c)
+		return 1;
+	if ('\f' == (unsigned char) c)
+		return 1;
+
+	return 0;
+}
+
+/** Returns true if the value of 'c' is a number */
+static inline int isdigit(int c)
+{
+	if (!isascii(c))
+		return 0;
+
+	if (((unsigned char) c >= '0') && ((unsigned char) c <= '9'))
+		return 1;
+
+	return 0;
+}
+
+/** Returns true if the value of 'c' is a lower case letter */
+static inline int islower(int c)
+{
+	if (!isascii(c))
+		return 0;
+
+	if (((unsigned char) c >= 'a') && ((unsigned char) c <= 'z'))
+		return 1;
+
+	return 0;
+}
+
+/** Returns true if the value of 'c' is an upper case letter */
+static inline int isupper(int c)
+{
+	if (!isascii(c))
+		return 0;
+
+	if (((unsigned char) c >= 'A') && ((unsigned char) c <= 'Z'))
+		return 1;
+
+	return 0;
+}
+
+/** Returns true if the value of 'c' is an alphabetic character */
+static inline int isalpha(int c)
+{
+	if (isupper(c) || islower(c))
+		return 1;
+
+	return 0;
+}
+
+/** Makes the input character lower case.\n Will do nothing if it 
+ * was something different than an upper case letter before. */
+static inline unsigned char tolower(unsigned char c)
+{
+	if (isupper(c))
+		c -= 'A'-'a';
+	return c;
+}
+
+/** Makes the input character upper case.\n Will do nothing if it 
+ * was something different than a lower case letter before. */
+static inline unsigned char toupper(unsigned char c)
+{
+	if (islower(c))
+		c -= 'a'-'A';
+	return c;
+}
+
+#endif
diff --git a/arch/x86/loader/include/limits.h b/arch/x86/loader/include/limits.h
new file mode 100644
index 000000000..4f311b8ad
--- /dev/null
+++ b/arch/x86/loader/include/limits.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *    * Neither the name of the University nor the names of its contributors
+ *      may be used to endorse or promote products derived from this
+ *      software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * author Stefan Lankes
+ * @file include/limits.h
+ * @brief Define constants related to numerical value-ranges of variable types
+ *
+ * This file contains define constants for the numerical
+ * ranges of the most typical variable types.
+ */
+
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Number of bits in a char */
+#define	CHAR_BIT	8
+
+/** Maximum value for a signed char */
+#define	SCHAR_MAX	0x7f
+/** Minimum value for a signed char */
+#define	SCHAR_MIN	(-0x7f - 1)
+
+/** Maximum value for an unsigned char */
+#define	UCHAR_MAX	0xff
+
+/** Maximum value for an unsigned short */
+#define	USHRT_MAX	0xffff
+/** Maximum value for a short */
+#define	SHRT_MAX	0x7fff
+/** Minimum value for a short */
+#define	SHRT_MIN	(-0x7fff - 1)
+
+/** Maximum value for an unsigned int */
+#define	UINT_MAX	0xffffffffU
+/** Maximum value for an int */
+#define	INT_MAX		0x7fffffff
+/** Minimum value for an int */
+#define	INT_MIN	(-0x7fffffff - 1)
+
+/** Maximum value for an unsigned long */
+#define	ULONG_MAX	0xffffffffUL
+/** Maximum value for a long */
+#define	LONG_MAX	0x7fffffffL
+/** Minimum value for a long */
+#define	LONG_MIN	(-0x7fffffffL - 1)
+
+/** Maximum value for an unsigned long long */
+#define	ULLONG_MAX	0xffffffffffffffffULL
+/** Maximum value for a long long */
+#define	LLONG_MAX	0x7fffffffffffffffLL
+/** Minimum value for a long long */
+#define	LLONG_MIN	(-0x7fffffffffffffffLL - 1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/arch/x86/loader/include/stddef.h b/arch/x86/loader/include/stddef.h
index 36f95f25f..76c2add7b 100644
--- a/arch/x86/loader/include/stddef.h
+++ b/arch/x86/loader/include/stddef.h
@@ -85,6 +85,14 @@ typedef char int8_t;
 /// 16 bit wide char type
 typedef unsigned short wchar_t;
 
+/** @brief String to long
+ *
+ * @return Long value of the parsed numerical string
+ */
+long _strtol(const char* str, char** endptr, int base);
+
+#define strtol(str, endptr, base)	_strtol((str), (endptr), (base))
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/arch/x86/loader/include/string.h b/arch/x86/loader/include/string.h
index 84ef64a67..3d51a9492 100644
--- a/arch/x86/loader/include/string.h
+++ b/arch/x86/loader/include/string.h
@@ -41,7 +41,9 @@ char *strncpy(char *dest, const char *src, size_t n);
 char *strcpy(char *dest, const char *src);
 int strcmp(const char *s1, const char *s2);
 int strncmp(const char *s1, const char *s2, size_t n);
-char *strstr(const char *s, const char *find);
+char *_strstr(const char *s, const char *find);
+
+#define strstr(s, find) _strstr((s), (find))
 
 #ifdef __cplusplus
 }
diff --git a/arch/x86/loader/main.c b/arch/x86/loader/main.c
index 12cba0777..c14aa5d06 100644
--- a/arch/x86/loader/main.c
+++ b/arch/x86/loader/main.c
@@ -42,6 +42,7 @@ extern const void kernel_start;
 extern const void kernel_end;
 extern const void bss_start;
 extern const void bss_end;
+extern size_t uartport;
 
 static int load_code(size_t viraddr, size_t phyaddr, size_t limit, uint32_t file_size, size_t mem_size)
 {
@@ -65,6 +66,7 @@ static int load_code(size_t viraddr, size_t phyaddr, size_t limit, uint32_t file
 	*((uint32_t*) (viraddr + 0x30)) = 0; // apicid
 	*((uint64_t*) (viraddr + 0x38)) = mem_size;
 	*((uint32_t*) (viraddr + 0x60)) = 1; // numa nodes
+	*((uint64_t*) (viraddr + 0x98)) = uartport;
 
 	// move file to a 2 MB boundary
 	for(size_t va = viraddr+(npages << PAGE_BITS)+displacement-sizeof(uint8_t); va >= viraddr+displacement; va-=sizeof(uint8_t))
diff --git a/arch/x86/loader/strstr.c b/arch/x86/loader/strstr.c
new file mode 100644
index 000000000..d2b687e86
--- /dev/null
+++ b/arch/x86/loader/strstr.c
@@ -0,0 +1,73 @@
+/*	$NetBSD: strstr.c,v 1.1 2005/12/20 19:28:52 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The code has been taken from NetBSD (sys/libkern/strstr.c) and is consequently
+ * BSD-licensed. Unnecessary functions have been removed and all typedefs required
+ * have been added.
+ */
+
+/* HermiCore prelude */
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+char *
+_strstr(s, find)
+	const char *s, *find;
+{
+	char c, sc;
+	size_t len;
+
+	if (BUILTIN_EXPECT(!s, 0))
+		return NULL;
+	if (BUILTIN_EXPECT(!find, 0))
+		return NULL;
+
+	if ((c = *find++) != 0) {
+		len = strlen(find);
+		do {
+			do {
+				if ((sc = *s++) == 0)
+					return (NULL);
+			} while (sc != c);
+		} while (strncmp(s, find, len) != 0);
+		s--;
+	}
+	return ((char *) s);
+}
diff --git a/arch/x86/loader/strtol.c b/arch/x86/loader/strtol.c
new file mode 100644
index 000000000..639e11e9f
--- /dev/null
+++ b/arch/x86/loader/strtol.c
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: @(#)strtol.c	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * The code has been taken from FreeBSD (sys/libkern/strtol.c) and is consequently
+ * BSD-licensed. Unnecessary functions have been removed and all typedefs required
+ * have been added.
+ */
+
+/* HermitCore prelude */
+#include <stddef.h>
+#include <ctype.h>
+#include <limits.h>
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long
+_strtol(nptr, endptr, base)
+	const char *nptr;
+	char **endptr;
+	int base;
+{
+	const char *s = nptr;
+	unsigned long acc;
+	unsigned char c;
+	unsigned long cutoff;
+	int neg = 0, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	do {
+		c = *s++;
+	} while (isspace(c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else if (c == '+')
+		c = *s++;
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for longs is
+	 * [-2147483648..2147483647] and the input base is 10,
+	 * cutoff will be set to 214748364 and cutlim to either
+	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
+	 * the number is too big, and we will return a range error.
+	 *
+	 * Set any if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+	cutlim = cutoff % (unsigned long)base;
+	cutoff /= (unsigned long)base;
+	for (acc = 0, any = 0;; c = *s++) {
+		if (!isascii(c))
+			break;
+		if (isdigit(c))
+			c -= '0';
+		else if (isalpha(c))
+			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LONG_MIN : LONG_MAX;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != 0)
+		*((const char **)endptr) = any ? s - 1 : nptr;
+	return (acc);
+}
diff --git a/arch/x86/loader/uart.c b/arch/x86/loader/uart.c
index d6013dd61..c5a75921e 100644
--- a/arch/x86/loader/uart.c
+++ b/arch/x86/loader/uart.c
@@ -92,28 +92,28 @@
 
 #define DEFAULT_UART_PORT	0 //0xc110
 
-static size_t	iobase = 0;
+size_t	uartport = 0;
 
 static inline unsigned char read_from_uart(uint32_t off)
 {
 	uint8_t c;
 
-	if (iobase)
-		c = inportb(iobase + off);
+	if (uartport)
+		c = inportb(uartport + off);
 
 	return c;
 }
 
 static void write_to_uart(uint32_t off, unsigned char c)
 {
-	if (iobase)
-		outportb(iobase + off, c);
+	if (uartport)
+		outportb(uartport + off, c);
 }
 
 /* Puts a single character on a serial device */
 int uart_putchar(unsigned char c)
 {
-	if (!iobase)
+	if (!uartport)
 		return 0;
 
 	write_to_uart(UART_TX, c);
@@ -126,7 +126,7 @@ int uart_puts(const char *text)
 {
 	size_t i, len = strlen(text);
 
-	if (!iobase)
+	if (!uartport)
 		return 0;
 
 	for (i = 0; i < len; i++)
@@ -137,7 +137,7 @@ int uart_puts(const char *text)
 
 static int uart_config(void)
 {
-	if (!iobase)
+	if (!uartport)
 		return 0;
 
 	/*
@@ -181,24 +181,16 @@ extern const void kernel_start;
 
 int uart_early_init(char* cmdline)
 {
-#if 1
-	// default value of our QEMU configuration
-	iobase = DEFAULT_UART_PORT;
-#else
-	if (BUILTIN_EXPECT(!cmdline, 0))
-		return -EINVAL;
+	char* str = NULL;
 
-	char* str = strstr(cmdline, "uart=");
-	if (!str)
-		return -EINVAL;
-
-	if (strncmp(str, "uart=io:", 8) == 0) {
-		iobase = strtol(str+8, (char **)NULL, 16);
-		if (!iobase)
-			iobase = DEFAULT_UART_PORT;
-			return -EINVAL;
+	if (!cmdline || ((str = strstr(cmdline, "uart=io:")) == NULL)) {
+		// default value of our QEMU configuration
+		uartport = DEFAULT_UART_PORT;
+	} else {
+			uartport = strtol(str+8, (char **)NULL, 16);
+			if (!uartport)
+				uartport = DEFAULT_UART_PORT;
 	}
-#endif
 
 	// configure uart
 	return uart_config();
@@ -206,6 +198,9 @@ int uart_early_init(char* cmdline)
 
 int uart_init(void)
 {
+	if (uartport)
+		return 0;
+
 #ifdef CONFIG_PCI
 	pci_info_t pci_info;
 	uint32_t bar = 0;
@@ -223,20 +218,20 @@ int uart_init(void)
 	if (pci_get_device_info(0x1b36, 0x0004, &pci_info) == 0)
 		goto Lsuccess;
 
-	iobase = DEFAULT_UART_PORT;
+	uartport = DEFAULT_UART_PORT;
 
 	return uart_config();
 
 Lsuccess:
-	iobase = pci_info.base[bar];
+	uartport = pci_info.base[bar];
 	//irq_install_handler(32+pci_info.irq, uart_handler);
-	kprintf("UART uses io address 0x%x\n", iobase);
+	kprintf("UART uses io address 0x%x\n", uartport);
 
 	// configure uart
 	return uart_config();
 #else
 	// default value of our QEMU configuration
-	iobase = DEFAULT_UART_PORT;
+	uartport = DEFAULT_UART_PORT;
 
 	// configure uart
 	return uart_config();