// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <cmdline.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utf_conversion.h>
#include <xefi.h>

#include "osboot.h"

#define CMDLINE_MAX_ITEMS 128
#define CMDLINE_MAX_STRINGDATA (PAGE_SIZE * 3)

static char buffer[CMDLINE_MAX_STRINGDATA];
static size_t buffer_next = 0;

typedef struct {
  char* key;
  char* val;
  size_t klen;
  size_t vlen;
} kv_t;

static kv_t entry[CMDLINE_MAX_ITEMS];
static size_t entry_count;

size_t cmdline_to_string(char* ptr, size_t max) {
  char* start = ptr;

  if (max == 0) {
    return 0;
  }

  for (size_t n = 0; n < entry_count; n++) {
    if ((entry[n].klen + entry[n].vlen + 3) > max) {
      // require space for: space + key + equal + value + null
      break;
    }
    if (n > 0) {
      *ptr++ = ' ';
      max--;
    }
    memcpy(ptr, entry[n].key, entry[n].klen);
    ptr += entry[n].klen;
    max -= entry[n].klen;
    if (entry[n].vlen) {
      *ptr++ = '=';
      max--;
      memcpy(ptr, entry[n].val, entry[n].vlen);
      ptr += entry[n].vlen;
      max -= entry[n].vlen;
    }
  }
  *ptr++ = 0;
  return ptr - start;
}

static void entry_add(const char* key, size_t klen, const char* val, size_t vlen) {
  if (klen == 0) {
    // empty keys are not allowed
    return;
  }

  if ((klen > 1024) || (vlen > 1024)) {
    // huge keys and values are not allowed
    return;
  }

  if ((sizeof(buffer) - buffer_next) < (klen + vlen + 2)) {
    // give up if it won't fit
    return;
  }

  size_t n;
  for (n = 0; n < entry_count; n++) {
    if ((entry[n].klen == klen) && !memcmp(key, entry[n].key, klen)) {
      goto write_value;
    }
  }
  if (n == CMDLINE_MAX_ITEMS) {
    // no space in table
    return;
  }

  // new entry
  entry_count++;
  entry[n].key = buffer + buffer_next;
  entry[n].klen = klen;
  memcpy(entry[n].key, key, klen);
  entry[n].key[klen] = 0;
  buffer_next += klen + 1;

write_value:
  entry[n].val = buffer + buffer_next;
  entry[n].vlen = vlen;
  memcpy(entry[n].val, val, vlen);
  entry[n].val[vlen] = 0;
  buffer_next += vlen + 1;
}

void cmdline_set(const char* key, const char* val) {
  entry_add(key, strlen(key), val, strlen(val));
}

void cmdline_append(const char* ptr, size_t len) {
  const char* key;
  const char* val;

restart:
  while (len > 0) {
    if (isspace(*ptr)) {
      ptr++;
      len--;
      continue;
    }
    key = ptr;
    while (len > 0) {
      if (*ptr == '=') {
        size_t klen = ptr - key;
        ptr++;
        len--;
        val = ptr;
        while ((len > 0) && !isspace(*ptr)) {
          len--;
          ptr++;
        }
        size_t vlen = ptr - val;
        entry_add(key, klen, val, vlen);
        goto restart;
      }
      if (isspace(*ptr)) {
        break;
      }
      ptr++;
      len--;
    }
    size_t klen = ptr - key;
    entry_add(key, klen, NULL, 0);
  }
}

// Get any load options from the image and append them to the boot arguments.
void cmdline_append_load_options(void) {
  size_t args_len = 0;

  efi_status status;
  size_t options_len;
  void* options;
  char16_t* wptr;
  uint8_t* args;
  uint8_t* ptr;

  status = xefi_get_load_options(&options_len, &options);

  if (status != EFI_SUCCESS) {
    printf("xefi_get_load_options failed: %zu\n", status);
    return;
  }

  args_len = options_len / sizeof(char16_t) + 1;
  status = gBS->AllocatePool(EfiLoaderData, args_len, (void**)&args);
  if (status != EFI_SUCCESS) {
    printf("allocating arg memory failed: %zu\n", status);
    goto alloc_fail;
  }

  wptr = options;
  ptr = args;
  zx_status_t result;
  size_t converted_args_len = args_len;

  result = utf16_to_utf8(options, options_len, args, &converted_args_len);
  if (result != ZX_OK) {
    printf("Could not convert options from UTF16->UTF8: %d\n", result);
    goto fail;
  }

  if (converted_args_len > args_len) {
    converted_args_len = args_len;
  }
  args[converted_args_len] = '\0';

  // Skip first argument which is the filename.
  ptr = args;
  while (*ptr && *ptr != ' ') {
    ptr++;
    converted_args_len--;
  }
  while (*ptr && *ptr == ' ') {
    ptr++;
    converted_args_len--;
  }

  cmdline_append((char*)ptr, converted_args_len);

fail:
  gBS->FreePool(args);

alloc_fail:
  gBS->FreePool(options);
}

const char* cmdline_get(const char* key, const char* _default) {
  size_t klen = strlen(key);
  for (size_t n = 0; n < entry_count; n++) {
    if ((entry[n].klen == klen) && !memcmp(key, entry[n].key, klen)) {
      return entry[n].val;
    }
  }
  return _default;
}

uint32_t cmdline_get_uint32(const char* key, uint32_t _default) {
  const char* val = cmdline_get(key, NULL);
  if (val == NULL) {
    return _default;
  }
  return atol(val);
}
