Pārlūkot izejas kodu

完善命令行参数解析 (#4)

LoGin 1 gadu atpakaļ
vecāks
revīzija
78b790fa8b
12 mainītis faili ar 761 papildinājumiem un 232 dzēšanām
  1. 5 1
      .vscode/settings.json
  2. 7 1
      apps/Makefile
  3. 115 0
      apps/helper.c
  4. 242 0
      apps/lib/cmdline.c
  5. 128 0
      apps/lib/string.c
  6. 60 65
      apps/lib/vsprintf.c
  7. 0 0
      apps/riscv-stub.c
  8. 22 21
      apps/stub.c
  9. 47 0
      inc/dragonstub/dragonstub.h
  10. 1 0
      inc/dragonstub/types.h
  11. 3 1
      inc/lib.h
  12. 131 143
      lib/init.c

+ 5 - 1
.vscode/settings.json

@@ -29,6 +29,10 @@
         "random": "c",
         "bitsperlong.h": "c",
         "div64.h": "c",
-        "posix_types.h": "c"
+        "posix_types.h": "c",
+        "kernel.h": "c",
+        "sysinfo.h": "c",
+        "const.h": "c",
+        "string.h": "c"
     }
 }

+ 7 - 1
apps/Makefile

@@ -87,7 +87,13 @@ endif
 
 
 
-DRAGON_STUB_FILES:= dragon_stub-main.c stub.c helper.c lib/vsprintf.c lib/hexdump.c lib/ctype.c
+DRAGON_STUB_FILES:= dragon_stub-main.c stub.c helper.c
+DRAGON_STUB_FILES += lib/vsprintf.c lib/hexdump.c lib/ctype.c lib/cmdline.c lib/string.c
+
+ifeq ($(ARCH), riscv64)
+	DRAGON_STUB_FILES += riscv-stub.c
+endif
+
 # 把*.c的列表转换为*.o的列表
 DRAGON_STUB_OBJS := $(patsubst %.c,%.o,$(DRAGON_STUB_FILES))
 

+ 115 - 0
apps/helper.c

@@ -4,6 +4,16 @@
 #include <lib.h>
 #include <dragonstub/dragonstub.h>
 
+bool efi_nochunk;
+bool efi_nokaslr = true;
+// bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
+bool efi_novamap;
+
+static bool efi_noinitrd;
+static bool efi_nosoftreserve;
+static bool efi_disable_pci_dma = false;
+// static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
+
 enum efistub_event {
 	EFISTUB_EVT_INITRD,
 	EFISTUB_EVT_LOAD_OPTIONS,
@@ -200,3 +210,108 @@ char *efi_convert_cmdline(EFI_LOADED_IMAGE *image, int *cmd_line_len)
 	*cmd_line_len = options_bytes;
 	return (char *)cmdline_addr;
 }
+
+/**
+ *	parse_option_str - Parse a string and check an option is set or not
+ *	@str: String to be parsed
+ *	@option: option name
+ *
+ *	This function parses a string containing a comma-separated list of
+ *	strings like a=b,c.
+ *
+ *	Return true if there's such option in the string, or return false.
+ */
+bool parse_option_str(const char *str, const char *option)
+{
+	while (*str) {
+		if (!strncmp(str, option, strlen(option))) {
+			str += strlen(option);
+			if (!*str || *str == ',')
+				return true;
+		}
+
+		while (*str && *str != ',')
+			str++;
+
+		if (*str == ',')
+			str++;
+	}
+
+	return false;
+}
+
+/**
+ * efi_parse_options() - Parse EFI command line options
+ * @cmdline:	kernel command line
+ *
+ * Parse the ASCII string @cmdline for EFI options, denoted by the efi=
+ * option, e.g. efi=nochunk.
+ *
+ * It should be noted that efi= is parsed in two very different
+ * environments, first in the early boot environment of the EFI boot
+ * stub, and subsequently during the kernel boot.
+ *
+ * Return:	status code
+ */
+efi_status_t efi_parse_options(char const *cmdline)
+{
+	size_t len;
+	efi_status_t status;
+	char *str, *buf;
+
+	if (!cmdline)
+		return EFI_SUCCESS;
+
+	len = strnlen(cmdline, COMMAND_LINE_SIZE - 1) + 1;
+	status = efi_bs_call(AllocatePool, EfiLoaderData, len, (void **)&buf);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	memcpy(buf, cmdline, len - 1);
+	buf[len - 1] = '\0';
+	str = skip_spaces(buf);
+
+	while (*str) {
+		char *param, *val;
+
+		str = next_arg(str, &param, &val);
+		if (!val && !strcmp(param, "--"))
+			break;
+
+		if (!strcmp(param, "nokaslr")) {
+			efi_nokaslr = true;
+		} else if (!strcmp(param, "quiet")) {
+			// efi_loglevel = CONSOLE_LOGLEVEL_QUIET;
+		} else if (!strcmp(param, "noinitrd")) {
+			efi_noinitrd = true;
+		}
+#ifdef CONFIG_X86_64
+		else if (IS_ENABLED(CONFIG_X86_64) &&
+			 !strcmp(param, "no5lvl")) {
+			efi_no5lvl = true;
+		}
+#endif
+		else if (!strcmp(param, "efi") && val) {
+			efi_nochunk = parse_option_str(val, "nochunk");
+			efi_novamap |= parse_option_str(val, "novamap");
+
+			// efi_nosoftreserve =
+			// 	IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) &&
+			// 	parse_option_str(val, "nosoftreserve");
+			efi_nosoftreserve = false;
+
+			if (parse_option_str(val, "disable_early_pci_dma"))
+				efi_disable_pci_dma = true;
+			if (parse_option_str(val, "no_disable_early_pci_dma"))
+				efi_disable_pci_dma = false;
+			if (parse_option_str(val, "debug")) {
+				// efi_loglevel = CONSOLE_LOGLEVEL_DEBUG;
+			}
+		} else if (!strcmp(param, "video") && val &&
+			   strstarts(val, "efifb:")) {
+			// efi_parse_option_graphics(val + strlen("efifb:"));
+		}
+	}
+	efi_bs_call(FreePool, buf);
+	return EFI_SUCCESS;
+}

+ 242 - 0
apps/lib/cmdline.c

@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * linux/lib/cmdline.c
+ * Helper functions generally used for parsing kernel command line
+ * and module options.
+ *
+ * Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.
+ *
+ * GNU Indent formatting options for this file: -kr -i8 -npsl -pcs
+ */
+
+#include <dragonstub/linux/const.h>
+#include <dragonstub/dragonstub.h>
+#include <dragonstub/linux/ctype.h>
+
+/*
+ *	If a hyphen was found in get_option, this will handle the
+ *	range of numbers, M-N.  This will expand the range and insert
+ *	the values[M, M+1, ..., N] into the ints array in get_options.
+ */
+
+static int get_range(char **str, int *pint, int n)
+{
+	int x, inc_counter, upper_range;
+
+	(*str)++;
+	upper_range = simple_strtol((*str), NULL, 0);
+	inc_counter = upper_range - *pint;
+	for (x = *pint; n && x < upper_range; x++, n--)
+		*pint++ = x;
+	return inc_counter;
+}
+
+/**
+ *	get_option - Parse integer from an option string
+ *	@str: option string
+ *	@pint: (optional output) integer value parsed from @str
+ *
+ *	Read an int from an option string; if available accept a subsequent
+ *	comma as well.
+ *
+ *	When @pint is NULL the function can be used as a validator of
+ *	the current option in the string.
+ *
+ *	Return values:
+ *	0 - no int in string
+ *	1 - int found, no subsequent comma
+ *	2 - int found including a subsequent comma
+ *	3 - hyphen found to denote a range
+ *
+ *	Leading hyphen without integer is no integer case, but we consume it
+ *	for the sake of simplification.
+ */
+
+int get_option(char **str, int *pint)
+{
+	char *cur = *str;
+	int value;
+
+	if (!cur || !(*cur))
+		return 0;
+	if (*cur == '-')
+		value = -simple_strtoull(++cur, str, 0);
+	else
+		value = simple_strtoull(cur, str, 0);
+	if (pint)
+		*pint = value;
+	if (cur == *str)
+		return 0;
+	if (**str == ',') {
+		(*str)++;
+		return 2;
+	}
+	if (**str == '-')
+		return 3;
+
+	return 1;
+}
+
+/**
+ *	get_options - Parse a string into a list of integers
+ *	@str: String to be parsed
+ *	@nints: size of integer array
+ *	@ints: integer array (must have room for at least one element)
+ *
+ *	This function parses a string containing a comma-separated
+ *	list of integers, a hyphen-separated range of _positive_ integers,
+ *	or a combination of both.  The parse halts when the array is
+ *	full, or when no more numbers can be retrieved from the
+ *	string.
+ *
+ *	When @nints is 0, the function just validates the given @str and
+ *	returns the amount of parseable integers as described below.
+ *
+ *	Returns:
+ *
+ *	The first element is filled by the number of collected integers
+ *	in the range. The rest is what was parsed from the @str.
+ *
+ *	Return value is the character in the string which caused
+ *	the parse to end (typically a null terminator, if @str is
+ *	completely parseable).
+ */
+
+char *get_options(const char *str, int nints, int *ints)
+{
+	bool validate = (nints == 0);
+	int res, i = 1;
+
+	while (i < nints || validate) {
+		int *pint = validate ? ints : ints + i;
+
+		res = get_option((char **)&str, pint);
+		if (res == 0)
+			break;
+		if (res == 3) {
+			int n = validate ? 0 : nints - i;
+			int range_nums;
+
+			range_nums = get_range((char **)&str, pint, n);
+			if (range_nums < 0)
+				break;
+			/*
+			 * Decrement the result by one to leave out the
+			 * last number in the range.  The next iteration
+			 * will handle the upper number in the range
+			 */
+			i += (range_nums - 1);
+		}
+		i++;
+		if (res == 1)
+			break;
+	}
+	ints[0] = i - 1;
+	return (char *)str;
+}
+
+/**
+ *	memparse - parse a string with mem suffixes into a number
+ *	@ptr: Where parse begins
+ *	@retptr: (output) Optional pointer to next char after parse completes
+ *
+ *	Parses a string into a number.  The number stored at @ptr is
+ *	potentially suffixed with K, M, G, T, P, E.
+ */
+
+unsigned long long memparse(const char *ptr, char **retptr)
+{
+	char *endptr; /* local pointer to end of parsed string */
+
+	unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
+
+	switch (*endptr) {
+	case 'E':
+	case 'e':
+		ret <<= 10;
+		fallthrough;
+	case 'P':
+	case 'p':
+		ret <<= 10;
+		fallthrough;
+	case 'T':
+	case 't':
+		ret <<= 10;
+		fallthrough;
+	case 'G':
+	case 'g':
+		ret <<= 10;
+		fallthrough;
+	case 'M':
+	case 'm':
+		ret <<= 10;
+		fallthrough;
+	case 'K':
+	case 'k':
+		ret <<= 10;
+		endptr++;
+		fallthrough;
+	default:
+		break;
+	}
+
+	if (retptr)
+		*retptr = endptr;
+
+	return ret;
+}
+
+
+/*
+ * Parse a string to get a param value pair.
+ * You can use " around spaces, but can't escape ".
+ * Hyphens and underscores equivalent in parameter names.
+ */
+char *next_arg(char *args, char **param, char **val)
+{
+	unsigned int i, equals = 0;
+	int in_quote = 0, quoted = 0;
+
+	if (*args == '"') {
+		args++;
+		in_quote = 1;
+		quoted = 1;
+	}
+
+	for (i = 0; args[i]; i++) {
+		if (isspace(args[i]) && !in_quote)
+			break;
+		if (equals == 0) {
+			if (args[i] == '=')
+				equals = i;
+		}
+		if (args[i] == '"')
+			in_quote = !in_quote;
+	}
+
+	*param = args;
+	if (!equals)
+		*val = NULL;
+	else {
+		args[equals] = '\0';
+		*val = args + equals + 1;
+
+		/* Don't include quotes in value. */
+		if (**val == '"') {
+			(*val)++;
+			if (args[i - 1] == '"')
+				args[i - 1] = '\0';
+		}
+	}
+	if (quoted && i > 0 && args[i - 1] == '"')
+		args[i - 1] = '\0';
+
+	if (args[i]) {
+		args[i] = '\0';
+		args += i + 1;
+	} else
+		args += i;
+
+	/* Chew up trailing spaces. */
+	return skip_spaces(args);
+}

+ 128 - 0
apps/lib/string.c

@@ -0,0 +1,128 @@
+
+#include <dragonstub/dragonstub.h>
+
+char *skip_spaces(const char *str)
+{
+	while (isspace(*str))
+		++str;
+	return (char *)str;
+}
+
+unsigned int atou(const char *s)
+{
+	unsigned int i = 0;
+	while (isdigit(*s))
+		i = i * 10 + (*s++ - '0');
+	return i;
+}
+
+/* Works only for digits and letters, but small and fast */
+#define TOLOWER(x) ((x) | 0x20)
+
+static unsigned int simple_guess_base(const char *cp)
+{
+	if (cp[0] == '0') {
+		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
+			return 16;
+		else
+			return 8;
+	} else {
+		return 10;
+	}
+}
+
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char *s)
+{
+	const char *sc;
+
+	for (sc = s; *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp, char **endp,
+				   unsigned int base)
+{
+	unsigned long long result = 0;
+
+	if (!base)
+		base = simple_guess_base(cp);
+
+	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
+		cp += 2;
+
+	while (isxdigit(*cp)) {
+		unsigned int value;
+
+		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
+		if (value >= base)
+			break;
+		result = result * base + value;
+		cp++;
+	}
+	if (endp)
+		*endp = (char *)cp;
+
+	return result;
+}
+
+long simple_strtol(const char *cp, char **endp, unsigned int base)
+{
+	if (*cp == '-')
+		return -simple_strtoull(cp + 1, endp, base);
+
+	return simple_strtoull(cp, endp, base);
+}
+
+int strcmp(const char *str1, const char *str2)
+{
+	const unsigned char *s1 = (const unsigned char *)str1;
+	const unsigned char *s2 = (const unsigned char *)str2;
+	int delta = 0;
+
+	while (*s1 || *s2) {
+		delta = *s1 - *s2;
+		if (delta)
+			return delta;
+		s1++;
+		s2++;
+	}
+	return 0;
+}
+
+int strncmp(const char *cs, const char *ct, size_t count)
+{
+	unsigned char c1, c2;
+
+	while (count) {
+		c1 = *cs++;
+		c2 = *ct++;
+		if (c1 != c2)
+			return c1 < c2 ? -1 : 1;
+		if (!c1)
+			break;
+		count--;
+	}
+	return 0;
+}
+
+size_t strnlen(const char *s, size_t maxlen)
+{
+	const char *es = s;
+	while (*es && maxlen) {
+		es++;
+		maxlen--;
+	}
+
+	return (es - s);
+}

+ 60 - 65
apps/lib/vsprintf.c

@@ -9,7 +9,6 @@
 #include <dragonstub/linux/byteorder.h>
 #include <dragonstub/linux/div64.h>
 
-
 struct printf_spec {
 	unsigned int type : 8; /* format_type enum */
 	signed int field_width : 24; /* width of output field */
@@ -90,7 +89,7 @@ static noinline_for_stack int skip_atoi(const char **s)
 
 static const u16 decpair[100] = {
 #define _(x) (__force u16) cpu_to_le16(((x % 10) | ((x / 10) << 8)) + 0x3030)
-	_( 0), _( 1), _( 2), _( 3), _( 4), _( 5), _( 6), _( 7), _( 8), _( 9),
+	_(0),  _(1),  _(2),  _(3),  _(4),  _(5),  _(6),	 _(7),	_(8),  _(9),
 	_(10), _(11), _(12), _(13), _(14), _(15), _(16), _(17), _(18), _(19),
 	_(20), _(21), _(22), _(23), _(24), _(25), _(26), _(27), _(28), _(29),
 	_(30), _(31), _(32), _(33), _(34), _(35), _(36), _(37), _(38), _(39),
@@ -188,14 +187,13 @@ static noinline_for_stack char *put_dec(char *buf, unsigned long long n)
 
 #elif BITS_PER_LONG == 32 && BITS_PER_LONG_LONG == 64
 
-static void
-put_dec_full4(char *buf, unsigned r)
+static void put_dec_full4(char *buf, unsigned r)
 {
 	unsigned q;
 
 	/* 0 <= r < 10^4 */
 	q = (r * 0x147b) >> 19;
-	*((u16 *)buf) = decpair[r - 100*q];
+	*((u16 *)buf) = decpair[r - 100 * q];
 	buf += 2;
 	/* 0 <= q < 100 */
 	*((u16 *)buf) = decpair[q];
@@ -208,13 +206,12 @@ put_dec_full4(char *buf, unsigned r)
  * helper will ever be asked to convert is 1,125,520,955.
  * (second call in the put_dec code, assuming n is all-ones).
  */
-static noinline_for_stack
-unsigned put_dec_helper4(char *buf, unsigned x)
+static noinline_for_stack unsigned put_dec_helper4(char *buf, unsigned x)
 {
-        uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
+	uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
 
-        put_dec_full4(buf, x - q * 10000);
-        return q;
+	put_dec_full4(buf, x - q * 10000);
+	return q;
 }
 
 /* Based on code by Douglas W. Jones found at
@@ -222,36 +219,36 @@ unsigned put_dec_helper4(char *buf, unsigned x)
  * (with permission from the author).
  * Performs no 64-bit division and hence should be fast on 32-bit machines.
  */
-static
-char *put_dec(char *buf, unsigned long long n)
+static char *put_dec(char *buf, unsigned long long n)
 {
 	uint32_t d3, d2, d1, q, h;
 
-	if (n < 100*1000*1000)
+	if (n < 100 * 1000 * 1000)
 		return put_dec_trunc8(buf, n);
 
-	d1  = ((uint32_t)n >> 16); /* implicit "& 0xffff" */
-	h   = (n >> 32);
-	d2  = (h      ) & 0xffff;
-	d3  = (h >> 16); /* implicit "& 0xffff" */
+	d1 = ((uint32_t)n >> 16); /* implicit "& 0xffff" */
+	h = (n >> 32);
+	d2 = (h)&0xffff;
+	d3 = (h >> 16); /* implicit "& 0xffff" */
 
 	/* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
 	     = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
-	q   = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
+	q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
 	q = put_dec_helper4(buf, q);
 
 	q += 7671 * d3 + 9496 * d2 + 6 * d1;
-	q = put_dec_helper4(buf+4, q);
+	q = put_dec_helper4(buf + 4, q);
 
 	q += 4749 * d3 + 42 * d2;
-	q = put_dec_helper4(buf+8, q);
+	q = put_dec_helper4(buf + 8, q);
 
 	q += 281 * d3;
 	buf += 12;
 	if (q)
 		buf = put_dec_trunc8(buf, q);
-	else while (buf[-1] == '0')
-		--buf;
+	else
+		while (buf[-1] == '0')
+			--buf;
 
 	return buf;
 }
@@ -548,12 +545,11 @@ static char *pointer_string(char *buf, char *end, const void *ptr,
 	return number(buf, end, (unsigned long int)ptr, spec);
 }
 
-
-static noinline_for_stack
-char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
-		 const char *fmt)
+static noinline_for_stack char *hex_string(char *buf, char *end, u8 *addr,
+					   struct printf_spec spec,
+					   const char *fmt)
 {
-	int i, len = 1;		/* if we pass '%ph[CDN]', field width remains
+	int i, len = 1; /* if we pass '%ph[CDN]', field width remains
 				   negative value, fallback to the default */
 	char separator;
 
@@ -600,9 +596,10 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
 	return buf;
 }
 
-static noinline_for_stack
-char *mac_address_string(char *buf, char *end, u8 *addr,
-			 struct printf_spec spec, const char *fmt)
+static noinline_for_stack char *mac_address_string(char *buf, char *end,
+						   u8 *addr,
+						   struct printf_spec spec,
+						   const char *fmt)
 {
 	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
 	char *p = mac_addr;
@@ -647,9 +644,7 @@ static char *default_pointer(char *buf, char *end, const void *ptr,
 	return pointer_string(buf, end, ptr, spec);
 }
 
-
-static char *err_ptr(char *buf, char *end, void *ptr,
-		     struct printf_spec spec)
+static char *err_ptr(char *buf, char *end, void *ptr, struct printf_spec spec)
 {
 	int err = PTR_ERR(ptr);
 	// const char *sym = errname(err);
@@ -825,38 +820,38 @@ static noinline_for_stack char *pointer(const char *fmt, char *buf, char *end,
 		/* [mM]F (FDDI) */
 		/* [mM]R (Reverse order; Bluetooth) */
 		return mac_address_string(buf, end, ptr, spec, fmt);
-	// case 'I': /* Formatted IP supported
-	// 				 * 4:	1.2.3.4
-	// 				 * 6:	0001:0203:...:0708
-	// 				 * 6c:	1::708 or 1::1.2.3.4
-	// 				 */
-	// case 'i': /* Contiguous:
-	// 				 * 4:	001.002.003.004
-	// 				 * 6:   000102...0f
-	// 				 */
-	// 	return ip_addr_string(buf, end, ptr, spec, fmt);
-	// case 'E':
-	// 	return escaped_string(buf, end, ptr, spec, fmt);
-	// case 'U':
-	// 	return uuid_string(buf, end, ptr, spec, fmt);
-	// case 'V':
-	// 	return va_format(buf, end, ptr, spec, fmt);
-	// case 'K':
-	// 	return restricted_pointer(buf, end, ptr, spec);
-	// case 'N':
-	// 	return netdev_bits(buf, end, ptr, spec, fmt);
-	// case '4':
-	// 	return fourcc_string(buf, end, ptr, spec, fmt);
-	// case 'a':
-	// 	return address_val(buf, end, ptr, spec, fmt);
-	// case 'd':
-	// 	return dentry_name(buf, end, ptr, spec, fmt);
-	// case 't':
-	// 	return time_and_date(buf, end, ptr, spec, fmt);
-	// case 'C':
-	// 	return clock(buf, end, ptr, spec, fmt);
-	// case 'D':
-	// 	return file_dentry_name(buf, end, ptr, spec, fmt);
+		// case 'I': /* Formatted IP supported
+		// 				 * 4:	1.2.3.4
+		// 				 * 6:	0001:0203:...:0708
+		// 				 * 6c:	1::708 or 1::1.2.3.4
+		// 				 */
+		// case 'i': /* Contiguous:
+		// 				 * 4:	001.002.003.004
+		// 				 * 6:   000102...0f
+		// 				 */
+		// 	return ip_addr_string(buf, end, ptr, spec, fmt);
+		// case 'E':
+		// 	return escaped_string(buf, end, ptr, spec, fmt);
+		// case 'U':
+		// 	return uuid_string(buf, end, ptr, spec, fmt);
+		// case 'V':
+		// 	return va_format(buf, end, ptr, spec, fmt);
+		// case 'K':
+		// 	return restricted_pointer(buf, end, ptr, spec);
+		// case 'N':
+		// 	return netdev_bits(buf, end, ptr, spec, fmt);
+		// case '4':
+		// 	return fourcc_string(buf, end, ptr, spec, fmt);
+		// case 'a':
+		// 	return address_val(buf, end, ptr, spec, fmt);
+		// case 'd':
+		// 	return dentry_name(buf, end, ptr, spec, fmt);
+		// case 't':
+		// 	return time_and_date(buf, end, ptr, spec, fmt);
+		// case 'C':
+		// 	return clock(buf, end, ptr, spec, fmt);
+		// case 'D':
+		// 	return file_dentry_name(buf, end, ptr, spec, fmt);
 #ifdef CONFIG_BLOCK
 	case 'g':
 		return bdev_name(buf, end, ptr, spec, fmt);

+ 0 - 0
apps/riscv-stub.c


+ 22 - 21
apps/stub.c

@@ -19,28 +19,29 @@ EFI_STATUS efi_handle_cmdline(EFI_LOADED_IMAGE *image, char **cmdline_ptr)
 		return EFI_OUT_OF_RESOURCES;
 	}
 
-// 	if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
-// 	    IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
-// 	    cmdline_size == 0) {
-// 		status = efi_parse_options(CONFIG_CMDLINE);
-// 		if (status != EFI_SUCCESS) {
-// 			efi_err("Failed to parse options\n");
-// 			goto fail_free_cmdline;
-// 		}
-// 	}
+	// 	if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+	// 	    IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+	// 	    cmdline_size == 0) {
+	// 		status = efi_parse_options(CONFIG_CMDLINE);
+	// 		if (status != EFI_SUCCESS) {
+	// 			efi_err("Failed to parse options\n");
+	// 			goto fail_free_cmdline;
+	// 		}
+	// 	}
 
-// 	if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
-// 		status = efi_parse_options(cmdline);
-// 		if (status != EFI_SUCCESS) {
-// 			efi_err("Failed to parse options\n");
-// 			goto fail_free_cmdline;
-// 		}
-// 	}
+	// if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
+	if (cmdline_size > 0) {
+		status = efi_parse_options(cmdline);
+		if (status != EFI_SUCCESS) {
+			efi_err("Failed to parse options\n");
+			goto fail_free_cmdline;
+		}
+	}
 
-// 	*cmdline_ptr = cmdline;
-// 	return EFI_SUCCESS;
+	*cmdline_ptr = cmdline;
+	return EFI_SUCCESS;
 
-// fail_free_cmdline:
-// 	efi_bs_call(free_pool, cmdline_ptr);
-// 	return status;
+fail_free_cmdline:
+	efi_bs_call(FreePool, cmdline_ptr);
+	return status;
 }

+ 47 - 0
inc/dragonstub/dragonstub.h

@@ -115,6 +115,8 @@ typedef struct {
 	const void *optional_data;
 } efi_load_option_unpacked_t;
 
+typedef EFI_LOADED_IMAGE efi_loaded_image_t;
+
 /* The macro below handles dispatching via the thunk if needed */
 
 #define efi_fn_call(inst, func, ...) ((inst)->func(__VA_ARGS__))
@@ -124,3 +126,48 @@ typedef struct {
 		__typeof__(inst) __inst = (inst);                 \
 		efi_fn_call(__inst, func, __inst, ##__VA_ARGS__); \
 	})
+
+/*
+ * This function handles the architcture specific differences between arm and
+ * arm64 regarding where the kernel image must be loaded and any memory that
+ * must be reserved. On failure it is required to free all
+ * all allocations it has made.
+ */
+efi_status_t
+handle_kernel_image(unsigned long *image_addr, unsigned long *image_size,
+		    unsigned long *reserve_addr, unsigned long *reserve_size,
+		    efi_loaded_image_t *image, efi_handle_t image_handle);
+
+char *skip_spaces(const char *str);
+long simple_strtol(const char *cp, char **endp, unsigned int base);
+unsigned int atou(const char *s);
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp, char **endp,
+				   unsigned int base);
+long simple_strtol(const char *cp, char **endp, unsigned int base);
+size_t strnlen(const char *s, size_t maxlen);
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char *s);
+int strncmp(const char *cs, const char *ct, size_t count);
+int strcmp(const char *str1, const char *str2);
+char *next_arg(char *args, char **param, char **val);
+
+/**
+ * strstarts - does @str start with @prefix?
+ * @str: string to examine
+ * @prefix: prefix to look for.
+ */
+static inline bool strstarts(const char *str, const char *prefix)
+{
+	return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
+efi_status_t efi_parse_options(char const *cmdline);

+ 1 - 0
inc/dragonstub/types.h

@@ -53,6 +53,7 @@ typedef u16 efi_char16_t; /* UNICODE character */
 typedef u64 efi_physical_addr_t;
 typedef void *efi_handle_t;
 
+
 typedef _Bool bool;
 
 enum { false = 0, true = 1 };

+ 3 - 1
inc/lib.h

@@ -94,4 +94,6 @@ extern EFI_RESTORE_TPL                  LibRuntimeRestoreTPL;
 void *memset(void *s, int c, __SIZE_TYPE__ n);
 
 void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n);
-void *memmove(void *dst, const void *src, uint64_t size);
+void *memmove(void *dst, const void *src, uint64_t size);
+
+size_t strnlen(const char *s, size_t maxlen);

+ 131 - 143
lib/init.c

@@ -16,16 +16,9 @@ Revision History
 
 #include "lib.h"
 
-VOID
-EFIDebugVariable (
-    VOID
-    );
-
-VOID
-InitializeLib (
-    IN EFI_HANDLE           ImageHandle,
-    IN EFI_SYSTEM_TABLE     *SystemTable
-    )
+VOID EFIDebugVariable(VOID);
+
+VOID InitializeLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
 /*++
 
 Routine Description:
@@ -40,142 +33,139 @@ Returns:
 
     None
 
---*/ 
+--*/
 {
-    EFI_LOADED_IMAGE        *LoadedImage;
-    EFI_STATUS              Status;
-    CHAR8                   *LangCode;
-
-    if (LibInitialized)
-	return;
-
-    LibInitialized = TRUE;
-    LibFwInstance = FALSE;
-    LibImageHandle = ImageHandle;
-
-    //
-    // Set up global pointer to the system table, boot services table,
-    // and runtime services table
-    //
-
-    ST = SystemTable;
-    BS = SystemTable->BootServices;
-    RT = SystemTable->RuntimeServices;
-    // ASSERT (CheckCrc(0, &ST->Hdr));
-    // ASSERT (CheckCrc(0, &BS->Hdr));
-    // ASSERT (CheckCrc(0, &RT->Hdr));
-
-    //
-    // Initialize pool allocation type
-    //
-
-    if (ImageHandle) {
-	Status = uefi_call_wrapper(
-	    BS->HandleProtocol,
-	    3,
-	    ImageHandle,
-	    &LoadedImageProtocol,
-	    (VOID*)&LoadedImage
-	);
-
-	if (!EFI_ERROR(Status)) {
-	    PoolAllocationType = LoadedImage->ImageDataType;
+	EFI_LOADED_IMAGE *LoadedImage;
+	EFI_STATUS Status;
+	CHAR8 *LangCode;
+
+	if (LibInitialized)
+		return;
+
+	LibInitialized = TRUE;
+	LibFwInstance = FALSE;
+	LibImageHandle = ImageHandle;
+
+	//
+	// Set up global pointer to the system table, boot services table,
+	// and runtime services table
+	//
+
+	ST = SystemTable;
+	BS = SystemTable->BootServices;
+	RT = SystemTable->RuntimeServices;
+	// ASSERT (CheckCrc(0, &ST->Hdr));
+	// ASSERT (CheckCrc(0, &BS->Hdr));
+	// ASSERT (CheckCrc(0, &RT->Hdr));
+
+	//
+	// Initialize pool allocation type
+	//
+
+	if (ImageHandle) {
+		Status = uefi_call_wrapper(BS->HandleProtocol, 3, ImageHandle,
+					   &LoadedImageProtocol,
+					   (VOID *)&LoadedImage);
+
+		if (!EFI_ERROR(Status)) {
+			PoolAllocationType = LoadedImage->ImageDataType;
+		}
+		EFIDebugVariable();
 	}
-	EFIDebugVariable ();
-    }
 
-    //
-    // Initialize Guid table
-    //
+	//
+	// Initialize Guid table
+	//
 
-    InitializeGuid();
+	InitializeGuid();
 
-    InitializeLibPlatform(ImageHandle,SystemTable);
+	InitializeLibPlatform(ImageHandle, SystemTable);
 
-    if (ImageHandle && UnicodeInterface == &LibStubUnicodeInterface) {
-        LangCode = LibGetVariable (VarLanguage, &EfiGlobalVariable);
-        InitializeUnicodeSupport (LangCode);
-        if (LangCode) {
-            FreePool (LangCode);
-        }
-    }
+	if (ImageHandle && UnicodeInterface == &LibStubUnicodeInterface) {
+		LangCode = LibGetVariable(VarLanguage, &EfiGlobalVariable);
+		InitializeUnicodeSupport(LangCode);
+		if (LangCode) {
+			FreePool(LangCode);
+		}
+	}
 }
 
-VOID
-InitializeUnicodeSupport (
-    CHAR8 *LangCode
-    )
+VOID InitializeUnicodeSupport(CHAR8 *LangCode)
 {
-    EFI_UNICODE_COLLATION_INTERFACE *Ui;
-    EFI_STATUS                      Status;
-    CHAR8                           *Languages;
-    UINTN                           Index, Position, Length;
-    UINTN                           NoHandles;
-    EFI_HANDLE                      *Handles;
-
-    //
-    // If we don't know it, lookup the current language code
-    //
-
-    LibLocateHandle (ByProtocol, &UnicodeCollationProtocol, NULL, &NoHandles, &Handles);
-    if (!LangCode || !NoHandles) {
-        goto Done;
-    }
-
-    //
-    // Check all driver's for a matching language code
-    //
-
-    for (Index=0; Index < NoHandles; Index++) {
-        Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], &UnicodeCollationProtocol, (VOID*)&Ui);
-        if (EFI_ERROR(Status)) {
-            continue;
-        }
-
-        //
-        // Check for a matching language code
-        //
-
-        Languages = Ui->SupportedLanguages;
-        Length = strlena(Languages);
-        for (Position=0; Position < Length; Position += ISO_639_2_ENTRY_SIZE) {
-
-            //
-            // If this code matches, use this driver
-            //
-
-            if (CompareMem (Languages+Position, LangCode, ISO_639_2_ENTRY_SIZE) == 0) {
-                UnicodeInterface = Ui;
-                goto Done;
-            }
-        }
-    }
+	EFI_UNICODE_COLLATION_INTERFACE *Ui;
+	EFI_STATUS Status;
+	CHAR8 *Languages;
+	UINTN Index, Position, Length;
+	UINTN NoHandles;
+	EFI_HANDLE *Handles;
+
+	//
+	// If we don't know it, lookup the current language code
+	//
+
+	LibLocateHandle(ByProtocol, &UnicodeCollationProtocol, NULL, &NoHandles,
+			&Handles);
+	if (!LangCode || !NoHandles) {
+		goto Done;
+	}
+
+	//
+	// Check all driver's for a matching language code
+	//
+
+	for (Index = 0; Index < NoHandles; Index++) {
+		Status = uefi_call_wrapper(BS->HandleProtocol, 3,
+					   Handles[Index],
+					   &UnicodeCollationProtocol,
+					   (VOID *)&Ui);
+		if (EFI_ERROR(Status)) {
+			continue;
+		}
+
+		//
+		// Check for a matching language code
+		//
+
+		Languages = Ui->SupportedLanguages;
+		Length = strlena(Languages);
+		for (Position = 0; Position < Length;
+		     Position += ISO_639_2_ENTRY_SIZE) {
+			//
+			// If this code matches, use this driver
+			//
+
+			if (CompareMem(Languages + Position, LangCode,
+				       ISO_639_2_ENTRY_SIZE) == 0) {
+				UnicodeInterface = Ui;
+				goto Done;
+			}
+		}
+	}
 
 Done:
-    //
-    // Cleanup
-    //
+	//
+	// Cleanup
+	//
 
-    if (Handles) {
-        FreePool (Handles);
-    }
+	if (Handles) {
+		FreePool(Handles);
+	}
 }
 
-VOID
-EFIDebugVariable (
-    VOID
-    )
+VOID EFIDebugVariable(VOID)
 {
-    EFI_STATUS      Status;
-    UINT32          Attributes;
-    UINTN           DataSize;
-    UINTN           NewEFIDebug;
-
-    DataSize = sizeof(EFIDebug);
-    Status = uefi_call_wrapper(RT->GetVariable, 5, L"EFIDebug", &EfiGlobalVariable, &Attributes, &DataSize, &NewEFIDebug);
-    if (!EFI_ERROR(Status)) {
-        EFIDebug = NewEFIDebug;
-    }
+	EFI_STATUS Status;
+	UINT32 Attributes;
+	UINTN DataSize;
+	UINTN NewEFIDebug;
+
+	DataSize = sizeof(EFIDebug);
+	Status = uefi_call_wrapper(RT->GetVariable, 5, L"EFIDebug",
+				   &EfiGlobalVariable, &Attributes, &DataSize,
+				   &NewEFIDebug);
+	if (!EFI_ERROR(Status)) {
+		EFIDebug = NewEFIDebug;
+	}
 }
 
 /*
@@ -189,26 +179,25 @@ EFIDebugVariable (
 
 void *memset(void *s, int c, __SIZE_TYPE__ n)
 {
-    unsigned char *p = s;
+	unsigned char *p = s;
 
-    while (n--)
-        *p++ = c;
+	while (n--)
+		*p++ = c;
 
-    return s;
+	return s;
 }
 
 void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n)
 {
-    const unsigned char *q = src;
-    unsigned char *p = dest;
+	const unsigned char *q = src;
+	unsigned char *p = dest;
 
-    while (n--)
-        *p++ = *q++;
+	while (n--)
+		*p++ = *q++;
 
-    return dest;
+	return dest;
 }
 
-
 /**
  * @brief 将数据从src搬运到dst,并能正确处理地址重叠的问题
  *
@@ -219,7 +208,7 @@ void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n)
  */
 void *memmove(void *dst, const void *src, uint64_t size)
 {
-    const char *_src = src;
+	const char *_src = src;
 	char *_dst = dst;
 
 	if (!size)
@@ -239,4 +228,3 @@ void *memmove(void *dst, const void *src, uint64_t size)
 
 	return dst;
 }
-