[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/bootargs/bootargs.c b/src/bsp/lk/lib/bootargs/bootargs.c
new file mode 100644
index 0000000..9febf84
--- /dev/null
+++ b/src/bsp/lk/lib/bootargs/bootargs.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2014 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <lib/bootargs.h>
+
+#include <trace.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include <lk/init.h>
+
+#if WITH_KERNEL_VM
+#include <kernel/vm.h>
+#endif
+
+#define LOCAL_TRACE 0
+
+/* saved by the main entry point in lk */
+extern ulong lk_boot_args[4];
+
+static bool boot_args_valid = false;
+static struct lk_boot_arg *boot_args;
+
+#define LK_BOOT_ARG_MAGIC 'lkbt'
+
+/* lk style boot args are spread across the 4 incoming argument pointers as follows:
+ *
+ * [0] = LK_BOOT_ARG_MAGIC
+ * [1] = pointer to lk_boot_arg list
+ * [2] = unused
+ * [3] = xor of ULONG_MAX and the previous 3
+ */
+
+#define LK_BOOT_ARG_TYPE_INITIAL 'args'
+#define LK_BOOT_ARG_TYPE_COMMAND_LINE 'cmdl'
+#define LK_BOOT_ARG_TYPE_BOOTIMAGE 'bimg'
+#define LK_BOOT_ARG_TYPE_END 0
+
+struct lk_boot_arg {
+ uint32_t type;
+ uint32_t len;
+
+ uint8_t data[];
+};
+
+struct lk_boot_arg_bootimage {
+ uint64_t offset;
+ size_t len;
+
+ char device[];
+};
+
+static void *find_end(void *buf, size_t buf_len)
+{
+ uint8_t *ptr = (uint8_t *)buf;
+ struct lk_boot_arg *arg = (struct lk_boot_arg *)ptr;
+
+ while (arg->type != LK_BOOT_ARG_TYPE_END) {
+ ptr += sizeof(struct lk_boot_arg) + arg->len;
+
+ if ((uintptr_t)ptr - (uintptr_t)buf > buf_len)
+ return NULL;
+
+ arg = (struct lk_boot_arg *)ptr;
+ }
+
+ return ptr;
+}
+
+status_t bootargs_start(void *buf, size_t buf_len)
+{
+ if (buf_len < sizeof(struct lk_boot_arg))
+ return ERR_NO_MEMORY;
+
+ memset(buf, 0, buf_len);
+
+ struct lk_boot_arg *arg = (struct lk_boot_arg *)buf;
+ arg->type = LK_BOOT_ARG_TYPE_INITIAL;
+ arg->len = 0;
+
+ return NO_ERROR;
+}
+
+status_t bootargs_add_command_line(void *buf, size_t buf_len, const char *str)
+{
+ struct lk_boot_arg *arg = find_end(buf, buf_len);
+ if (!arg)
+ return ERR_NO_MEMORY;
+
+ arg->type = LK_BOOT_ARG_TYPE_COMMAND_LINE;
+ arg->len = ROUNDUP(strlen(str) + 1, 4);
+ memset(arg->data, 0, arg->len);
+ strcpy((char *)arg->data, str);
+
+ return NO_ERROR;
+}
+
+status_t bootargs_add_bootimage_pointer(void *buf, size_t buf_len, const char *device, uint64_t offset, size_t len)
+{
+ struct lk_boot_arg *arg = find_end(buf, buf_len);
+ if (!arg)
+ return ERR_NO_MEMORY;
+
+ arg->type = LK_BOOT_ARG_TYPE_BOOTIMAGE;
+ size_t string_len = device ? ROUNDUP(strlen(device) + 1, 4) : 0;
+ arg->len = string_len + sizeof(struct lk_boot_arg_bootimage);
+
+ struct lk_boot_arg_bootimage *bi = (struct lk_boot_arg_bootimage *)arg->data;
+
+ bi->offset = offset;
+ bi->len = len;
+ if (device) {
+ memset(bi->device, 0, string_len);
+ strcpy(bi->device, device);
+ }
+
+ return NO_ERROR;
+}
+
+void bootargs_generate_lk_arg_values(ulong buf, ulong args[4])
+{
+ args[0] = LK_BOOT_ARG_MAGIC;
+ args[1] = buf;
+ args[2] = 0;
+ args[3] = ULONG_MAX ^ args[0] ^ args[1] ^ args[2];
+}
+
+static void bootargs_init_hook(uint level)
+{
+ LTRACE_ENTRY;
+
+ /* see if there are any lk style boot arguments here */
+ if (lk_boot_args[0] != LK_BOOT_ARG_MAGIC) {
+ LTRACEF("failed magic check\n");
+ return;
+ }
+
+ if (lk_boot_args[3] != (ULONG_MAX ^ lk_boot_args[0] ^ lk_boot_args[1] ^ lk_boot_args[2])) {
+ LTRACEF("failed checksum\n");
+ return;
+ }
+
+ /* parse the boot arg pointer */
+#if WITH_KERNEL_VM
+ boot_args = paddr_to_kvaddr(lk_boot_args[1]);
+#else
+ boot_args = (void *)lk_boot_args[1];
+#endif
+
+ if (!boot_args) {
+ LTRACEF("null or invalid boot pointer\n");
+ return;
+ }
+
+ /* see if the initial entry is the right one */
+ if (boot_args[0].type != LK_BOOT_ARG_TYPE_INITIAL) {
+ LTRACEF("bad initial arg\n");
+ return;
+ }
+
+ /* looks good */
+ boot_args_valid = true;
+
+ LTRACEF("valid args found\n");
+}
+
+bool bootargs_are_valid(void)
+{
+ return boot_args_valid;
+}
+
+static struct lk_boot_arg *find_tag(uint32_t tag)
+{
+ if (!boot_args_valid)
+ return NULL;
+
+ struct lk_boot_arg *arg = boot_args;
+
+ while (arg->type != LK_BOOT_ARG_TYPE_END) {
+ if (arg->type == tag)
+ return arg;
+
+ arg = (struct lk_boot_arg *)((uintptr_t)arg + sizeof(struct lk_boot_arg) + arg->len);
+ }
+
+ return NULL;
+}
+
+const char *bootargs_get_command_line(void)
+{
+ struct lk_boot_arg *arg = find_tag(LK_BOOT_ARG_TYPE_COMMAND_LINE);
+ if (!arg)
+ return NULL;
+
+ // XXX validate it
+
+ return (const char *)arg->data;
+}
+
+status_t bootargs_get_bootimage_pointer(uint64_t *offset, size_t *len, const char **device)
+{
+ struct lk_boot_arg *arg = find_tag(LK_BOOT_ARG_TYPE_BOOTIMAGE);
+ if (!arg)
+ return ERR_NOT_FOUND;
+
+ // XXX validate it
+
+ struct lk_boot_arg_bootimage *bi = (struct lk_boot_arg_bootimage *)arg->data;
+
+ if (device) {
+ if (arg->len != sizeof(struct lk_boot_arg_bootimage)) {
+ /* string is present */
+ *device = bi->device;
+ } else {
+ *device = NULL;
+ }
+ }
+
+ if (offset)
+ *offset = bi->offset;
+ if (len)
+ *len = bi->len;
+
+ return NO_ERROR;
+}
+
+LK_INIT_HOOK(bootargs, bootargs_init_hook, LK_INIT_LEVEL_THREADING);
+