+++ /dev/null
-/**
- * \file
- * \brief Multiboot information creator
- *
- * This program creates a multiboot informaton structure based on the pre-
- * processed menu.lst file
- */
-
-/*
- * Copyright (c) 2014 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include "elf.h"
-
-#define MAX_LINE_SIZE 2048
-#define MAX_CMD_SIZE 64
-#define MAX_ARGS_SIZE 1024
-#define MAX_IMAGE_SIZE 256
-
-#define MAX_MODULES 256
-
-static char *kernel_cmd_line;
-static unsigned int kernel_offset;
-static unsigned int kernel_length;
-static unsigned int module_offset[MAX_MODULES];
-static unsigned int module_length[MAX_MODULES];
-static char *module_cmd_line[MAX_MODULES];
-
-
-int
-main(int argc,
- char *argv[])
-{
- int n_modules = 0;
- int n_mmaps = 0;
-
- if (argc < 3) {
- printf("Usage: %s <menu.lst> <output.c>\n", argv[0]);
- return 0;
- }
-
- FILE *f = fopen(argv[1], "r");
- assert((f != NULL) && "Could not open input file");
-
- FILE *o = fopen(argv[2], "w");
- assert((o != NULL) && "Could not open output file");
-
- // Output initial part of file: include basic types etc.
- fprintf(o, "#include <assert.h>\n");
- fprintf(o, "#include <stdio.h>\n");
- fprintf(o, "#include <stdint.h>\n");
- fprintf(o, "#include <stddef.h>\n");
- fprintf(o, "#include <string.h>\n");
- fprintf(o, "#include <barrelfish_kpi/types.h>\n");
- fprintf(o, "#include <errors/errno.h>\n");
- fprintf(o, "#include <elf/elf.h>\n");
- fprintf(o, "#include \"mbi.h\"\n");
- fprintf(o, "#include \"../kernel/include/multiboot.h\"\n");
-
- // Process menu.lst, generating definitions
- uint64_t offset;
- uint64_t length;
-
- char cmd[MAX_CMD_SIZE], args[MAX_ARGS_SIZE], image[MAX_IMAGE_SIZE];
- while (!feof(f)) {
- char line[MAX_LINE_SIZE], *l;
-
- cmd[0] = args[0] = image[0] = line[0] = '\0';
-
- /*
- * input format
- *
- * CMD IMAGE OFFSET SIZE ARGS
- * kernel /k1om/sbin/cpu 0 1006840 loglevel=4
- *
- */
- l = fgets(line, MAX_LINE_SIZE, f);
- if (!l) {
- /* error or EOF, check for EOF with next iteration */
- continue;
- }
- sscanf(line, "%s %s %lu %lu %[^\n]", cmd, image, &offset, &length, args);
-
- if (!strcmp(cmd, "kernel")) {
- printf(" +Kernel: %s, offset=0x%lx, length=0x%lx, args=%s\n",
- image, offset, length, args);
- kernel_cmd_line = malloc(strlen(line) + 1);
- kernel_length = length;
- kernel_offset = offset;
- sprintf(kernel_cmd_line, "%s %s", image, args);
- } else if (!strcmp(cmd, "module")) {
- assert(n_modules < MAX_MODULES);
- module_cmd_line[n_modules] = malloc(strlen(line) + 1);
- module_length[n_modules] = length;
- module_offset[n_modules] = offset;
- sprintf(module_cmd_line[n_modules], "%s %s", image, args);
- printf(" +Module [%d]: %s, offset=0x%lx, length=0x%lx, args=%s\n", n_modules,
- image, offset, length, args);
- n_modules++;
- } else if (!strcmp(cmd, "mmap")) {
- //uint64_t base, len;
- int type;
- sscanf(line, "%s %s %lx %lx %i", cmd, image, &offset, &length, &type);
- sscanf(args, "%i", &type);
- printf(" +MMAP %d: [0x%" PRIx64 ", 0x%" PRIx64 "], type %d\n",
- n_mmaps, offset, length, type);
- fprintf(o, "static uint64_t mbi_mmap%d[] = {0x%lx, 0x%lx, %d};\n",
- n_mmaps, offset, length, type);
- n_mmaps++;
- } else {
- bool iscmd = false;
- for (int i = 0; i < strlen(cmd); i++) {
- if (cmd[i] == '#') {
- break;
- }
- if (!isspace(cmd[i])) {
- iscmd = true;
- break;
- }
- }
- if (iscmd) {
- printf(" -Ignoring command '%s'\n", cmd);
- }
- }
- }
-
- // Generate multiboot-structure initialization code
- fprintf(o, "static struct multiboot_modinfo mbi_mods[%d];\n", n_modules + 1);
- fprintf(o, "static struct multiboot_mmap mbi_mmaps[%d];\n", n_mmaps);
- fprintf(o, "static struct multiboot_info mbi;\n\n");
- fprintf(o, "struct multiboot_info *get_multiboot(void) {\n");
-
- // Flags:
- fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_CMDLINE;\n");
- fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MODS;\n");
- fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS;\n");
- fprintf(o, " mbi.flags |= MULTIBOOT_INFO_FLAG_HAS_MMAP;\n");
-
- // Kernel command line:
- fprintf(o, " mbi.cmdline = (uint32_t)(uint64_t) \"%s\";\n", kernel_cmd_line);
-
- // Modules:
- fprintf(o, " mbi.mods_count = %d;\n", n_modules + 1);
- fprintf(o, " mbi.mods_addr = (uint32_t)(uint64_t) mbi_mods;\n");
- fprintf(o, " mbi_mods[0].mod_start = (uint32_t) 0x%x;\n", kernel_offset);
- fprintf(o, " mbi_mods[0].mod_end = (uint32_t) 0x%x;\n",
- kernel_offset + kernel_length);
- fprintf(o, " mbi_mods[0].string = (uint32_t)(uint64_t) \"%s\";\n",
- kernel_cmd_line);
-
- for (int i = 0; i < n_modules; i++) {
- fprintf(o, " mbi_mods[%d].mod_start = (uint32_t) 0x%x;\n", i + 1,
- module_offset[i]);
- fprintf(o, " mbi_mods[%d].mod_end = (uint32_t) 0x%x;\n", i + 1,
- module_offset[i] + module_length[i]);
- fprintf(o, " mbi_mods[%d].string = (uint32_t)(uint64_t) \"%s\";\n", i + 1,
- module_cmd_line[i]);
- }
-
- // MMAPS:
- fprintf(o, " mbi.mmap_length = sizeof(mbi_mmaps);\n");
- fprintf(o, " mbi.mmap_addr = (uint32_t)(uint64_t) mbi_mmaps;\n");
- for (int i = 0; i < n_mmaps; i++) {
- fprintf(o, " mbi_mmaps[%d].size = sizeof(struct multiboot_mmap);\n", i);
- fprintf(o, " mbi_mmaps[%d].base_addr = mbi_mmap%d[0];\n", i, i);
- fprintf(o, " mbi_mmaps[%d].length = mbi_mmap%d[1];\n", i, i);
- fprintf(o, " mbi_mmaps[%d].type = (int)mbi_mmap%d[2];\n", i, i);
- }
- fprintf(o, " return &mbi;\n");
- fprintf(o, "}\n\n");
-
- fclose(f);
- fclose(o);
-
- return 0;
-}
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
+
#include <barrelfish/barrelfish.h>
#include <spawndomain/spawndomain.h>
#include <vfs/vfs.h>
#include <elf/elf.h>
#include <xeon_phi/xeon_phi.h>
+#include <tftp/tftp.h>
+
+#include <../kernel/include/multiboot.h>
#include <dev/xeon_phi/xeon_phi_boot_dev.h>
#include <dev/xeon_phi/xeon_phi_apic_dev.h>
#include "interphi.h"
#include "sleep.h"
+#define TFTP_BUF_SIZE (1<<20)
+#define TFTP_BUF_SIZE_MODULES (1<<30)
+
+typedef errval_t (*loadfile_fn_t)(char *path, void *buf, size_t buflen, size_t *ret_size);
+
#define BOOT_TIMEOUT 3000
#define BOOT_COUNTER 0xFFFFF
}
}
+/**
+ * \brief generates the cmdline supplied to the card kernel
+ *
+ * \param phi the card information structure
+ * \param load_offset offset where to load the cmdline
+ * \param ret_size size of the cmdline in bytes
+ */
+static errval_t load_cmdline(struct xeon_phi *phi, lvaddr_t load_offset)
+{
+ uint32_t cmdlen = 0;
+
+ struct xeon_phi_boot_params *bp;
+ bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
+
+ void *buf = (void *) (phi->apt.vbase + load_offset);
+
+ if (phi->cmdline) {
+ cmdlen += sprintf(buf + cmdlen, "%s", phi->cmdline);
+ }
+
+ cmdlen += sprintf(buf + cmdlen, "card_id=%i", phi->id);
+
+ /*
+ * id
+ */
+ /*
+ * TODO: Add multihop / communication information here..
+ */
+
+ XBOOT_DEBUG("cmdline @ 0x%" PRIx32 " '%s'\n", (uint32_t)load_offset, (char*)buf);
+
+ phi->cmdline = buf;
+ phi->cmdlen = cmdlen;
+
+
+ bp->cmdline_ptr = (uint32_t)(load_offset);
+ bp->cmdline_size = (uint32_t)cmdlen;
+
+ return SYS_ERR_OK;
+}
+
+static errval_t bootstrap_notify(struct xeon_phi *phi)
+{
+ // set the bootimage size to tell the bootloader
+ xeon_phi_boot_os_size_rawwr(&boot_registers, phi->os_size);
+
+ uint64_t memsize = get_adapter_memsize();
+
+ uint64_t reserved = (memsize * MEMORY_RESERVE_PERCENT / 100);
+
+ // Keep in mind maximum uos reserve size is uint32_t, so we never overflow
+ reserved = MIN(reserved, UOS_RESERVE_SIZE_MAX);
+ reserved = MAX(reserved, UOS_RESERVE_SIZE_MIN);
+
+ // Always align uos reserve size to a page
+ reserved = (reserved & ~(BASE_PAGE_SIZE - 1));
+
+ xeon_phi_boot_res_size_rawwr(&boot_registers, (uint32_t) reserved);
+
+ // sending the bootstrap interrupt
+ xeon_phi_apic_icr_lo_t icr_lo = xeon_phi_apic_icr_lo_default;
+ icr_lo = xeon_phi_apic_icr_lo_vector_insert(icr_lo, xeon_phi_apic_vec_bsp);
+ icr_lo = xeon_phi_apic_icr_lo_boot_notify_insert(icr_lo, 0x1);
+
+ assert(icr_lo == (229 | (1 << 13)));
+
+ xeon_phi_apic_icr_hi_wr(&apic_registers, xeon_phi_apic_bootstrap, phi->apicid);
+
+ xeon_phi_apic_icr_lo_wr(&apic_registers, xeon_phi_apic_bootstrap, icr_lo);
+
+ return SYS_ERR_OK;
+}
+
+/*
+ * -------------------------------------------------------------------------------
+ * VFS helper function
+ * -------------------------------------------------------------------------------
+ */
-static errval_t load_module(char *path,
- uint8_t use_nfs,
- void *buf,
- uint64_t *ret_size)
+static vfs_handle_t file_open(char *file, uint8_t nfs)
{
errval_t err;
- char *mod_path = path;
- if (use_nfs) {
- size_t path_size = strlen(path) + strlen(XEON_PHI_NFS_MNT) + 2;
- mod_path = malloc(path_size);
- if (mod_path == NULL) {
- return LIB_ERR_MALLOC_FAIL;
+ vfs_handle_t fh;
+ char *path = file;
+ if (nfs) {
+ size_t path_size = strlen(file) + strlen(XEON_PHI_NFS_MNT) + 2;
+ path = malloc(path_size);
+ if (path == NULL) {
+ return NULL;
}
- if (path[0] == '/') {
- snprintf(mod_path, path_size, "%s%s", XEON_PHI_NFS_MNT, path);
+ if (file[0] == '/') {
+ snprintf(path, path_size, "%s%s", XEON_PHI_NFS_MNT, file);
} else {
- snprintf(mod_path, path_size, "%s/%s", XEON_PHI_NFS_MNT, path);
+ snprintf(path, path_size, "%s/%s", XEON_PHI_NFS_MNT, file);
}
}
-
- /* read file into memory */
- vfs_handle_t fh;
- err = vfs_open(mod_path, &fh);
- if (err_is_fail(err)) {
- return err_push(err, SPAWN_ERR_LOAD);
+ err = vfs_open(path, &fh);
+ if (nfs) {
+ free(path);
}
-
- struct vfs_fileinfo info;
- err = vfs_stat(fh, &info);
- if (err_is_fail(err)) {
- vfs_close(fh);
- return err_push(err, SPAWN_ERR_LOAD);
+ switch(err_no(err)) {
+ case SYS_ERR_OK :
+ return fh;
+ break;
+ case FS_ERR_NOTFOUND :
+ err = vfs_open(file, &fh);
+ if (err_is_ok(err)) {
+ return fh;
+ }
+ return NULL;
+ break;
+ default:
+ return NULL;
}
- assert(info.type == VFS_FILE);
-
- uint8_t *image = buf;
+ return NULL;
+}
- size_t pos = 0, readlen;
+static errval_t file_load(vfs_handle_t fh, void *buf, size_t length)
+{
+ errval_t err;
+ size_t pos = 0, readlen = 0;
do {
- err = vfs_read(fh, &image[pos], info.size - pos, &readlen);
+ err = vfs_read(fh, buf+pos, length - pos, &readlen);
if (err_is_fail(err)) {
- vfs_close(fh);
- return err_push(err, SPAWN_ERR_LOAD);
+ return err;
} else if (readlen == 0) {
- vfs_close(fh);
return SPAWN_ERR_LOAD; // XXX
} else {
pos += readlen;
}
- } while (err_is_ok(err) && readlen > 0 && pos < info.size);
-
- err = vfs_close(fh);
- if (err_is_fail(err)) {
- DEBUG_ERR(err, "failed to close file %s", path);
- }
-
- if (ret_size) {
- *ret_size = info.size;
- }
+ } while (err_is_ok(err) && readlen > 0 && pos < length);
return SYS_ERR_OK;
-
}
-/**
- * \brief Loads the bootloader image onto the card
- *
- * \param phi the xeon phi card information
- * \param xloader_img name of the bootloader image
- * \param ret_imgsize returned image size
- *
- * Note: it is important that the bootloader just uses statically allocated
- * memory and does not exceed its image size with additional memory.
- * Otherwise the CMD line or the multiboot image will be overwritten.
- */
-static errval_t load_bootloader(struct xeon_phi *phi,
- char *xloader_img)
+
+static errval_t download_file_vfs(char *file, void *card_buffer, size_t use_nfs,
+ size_t *bytes)
{
errval_t err;
-#if 0
- /*
- * find the boot loader image in the host multiboot
- */
- struct mem_region *module = multiboot_find_module(bi, xloader_img);
- if (module == NULL) {
- return SPAWN_ERR_FIND_MODULE;
- }
- lvaddr_t binary = 0;
- size_t imgsize = 0;
+ vfs_handle_t fh = file_open(file, use_nfs);
+ if (fh == NULL) {
+ return FS_ERR_INVALID_FH;
+ }
- err = spawn_map_module(module, &imgsize, &binary, NULL);
+ struct vfs_fileinfo info;
+ err = vfs_stat(fh, &info);
if (err_is_fail(err)) {
- return err_push(err, SPAWN_ERR_ELF_MAP);
+ goto out;
}
- imgsize = module->mrmod_size;
+ if (bytes) {
+ *bytes = info.size;
+ }
+ assert(info.type == VFS_FILE);
+ assert(info.size < 4UL<<30);
+ err = file_load(fh, card_buffer, info.size);
+ out:
+ vfs_close(fh);
+ return err;
+}
- /*
- * get the load offset: we do not want to write into the boot loade
- */
- lvaddr_t loadoffset = get_load_offset(phi);
+/*
+ * -------------------------------------------------------------------------------
+ * boot loader
+ * -------------------------------------------------------------------------------
+ */
- get_adapter_memsize();
+#define SETUP_SECTORS 2
+#define SECTOR_SIZE 512
+#define HEADER_SIZE (SETUP_SECTORS*SECTOR_SIZE)
- phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);
+static errval_t download_bootloader_generic(struct xeon_phi *phi, char *bootloader,
+ loadfile_fn_t loadfn, size_t args)
+{
+ errval_t err;
- XBOOT_DEBUG("Loading xloader onto card... offset = 0x%lx\n", loadoffset);
+ lvaddr_t loadoffset = get_load_offset(phi);
+ size_t imgsize;
- memcpy((void *) (phi->apt.vbase + loadoffset), (void *) binary, imgsize);
+ char *buf = (void *) (phi->apt.vbase + loadoffset);
-#endif
- lvaddr_t loadoffset = get_load_offset(phi);
- uint64_t imgsize;
+ /* fill in the header */
+ memset(buf, 0, HEADER_SIZE);
- void *buf = (void *) (phi->apt.vbase + loadoffset);
+ /*
+ * This is the signature. Without this the kernel does not boot.
+ * Signature is reads "HdrS"
+ */
+ buf[514] = 0x48;
+ buf[515] = 0x64;
+ buf[516] = 0x72;
+ buf[517] = 0x53;
+ buf[0x1f1] = SETUP_SECTORS-1;
- err = load_module(xloader_img, phi->use_nfs, buf, &imgsize);
+ err = loadfn(bootloader, buf + HEADER_SIZE, args, &imgsize);
if (err_is_fail(err)) {
return err;
}
+ size_t sys_size = (imgsize + 15) / 16;
+ buf[0x1f4] = sys_size;
+ buf[0x1f5] = sys_size >> 8;
+ buf[0x1f6] = sys_size >> 16;
+ buf[0x1f7] = sys_size >> 24;
+
phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);
phi->os_offset = loadoffset;
phi->os_size = imgsize;
+ XBOOT_DEBUG("Xeon Phi bootloader %s loaded @ 0x%lx size %lu kB\n", bootloader,
+ loadoffset, imgsize >> 10);
+
return SYS_ERR_OK;
}
-/**
- *
+
+static inline errval_t download_bootloader_vfs(struct xeon_phi *phi, char *bootloader,
+ uint8_t use_nfs)
+{
+ return download_bootloader_generic(phi, bootloader, download_file_vfs, use_nfs);
+}
+
+static inline errval_t download_bootloader_tftp(struct xeon_phi *phi, char *bootloader)
+{
+ return download_bootloader_generic(phi, bootloader, tftp_client_read_file,
+ TFTP_BUF_SIZE_MODULES);
+}
+
+
+/*
+ * -------------------------------------------------------------------------------
+ * multiboot modules
+ * -------------------------------------------------------------------------------
*/
-static errval_t load_multiboot_image(struct xeon_phi *phi,
- char *multiboot_img,
- lvaddr_t load_offset)
+
+static uint32_t prepare_multiboot_strings(void *strings, char **mods,
+ uint32_t num_mods)
{
- errval_t err;
+ uint32_t bytes = 0;
+ for (uint32_t i = 0; i < num_mods; ++i) {
+ bytes += snprintf(strings+bytes, 1<<20, "%s", mods[i]) + 1;
+ }
+ return bytes;
+}
- assert(phi->os_offset != 0);
+static inline char *get_module_path(char *cmdline)
+{
+ while(*cmdline) {
+ if (isspace((int)*cmdline)) {
+ return cmdline;
+ }
+ cmdline++;
+ }
+ return cmdline;
+}
-#if 0
+static uint32_t prepare_multiboot_info(void *aptvbase, lpaddr_t offset,
+ char **mmaps, uint32_t num_mods,
+ uint32_t num_mmaps)
+{
+ void *mbibuf = aptvbase + offset;
/*
- * find the boot loader image in the host multiboot
+ * Layout of multi boot information on card:
+ * [multiboot_info]
+ * [n x multiboot_modinfo]
+ * [m x multiboot_mmap]
+ * [strings]
*/
- struct mem_region *module = multiboot_find_module(bi, multiboot_img);
- if (module == NULL) {
- return SPAWN_ERR_FIND_MODULE;
+
+ /* set the host virtual pointers of the multiboot structures */
+ struct multiboot_info *mbi = mbibuf;
+ struct multiboot_modinfo *mbi_mods = (struct multiboot_modinfo *)(mbi + 1);
+ struct multiboot_mmap *mbi_mmaps = (struct multiboot_mmap *)(mbi_mods + num_mods);
+
+ /* card physical modules array */
+ offset += (uint32_t)sizeof(struct multiboot_info);
+ mbi->mods_count = num_mods;
+ mbi->mods_addr = offset;
+
+ /* card physical mmap array */
+ offset += num_mods * (uint32_t)sizeof(struct multiboot_modinfo);
+ mbi->mmap_addr = offset;
+ mbi->mmap_length = num_mmaps * sizeof(struct multiboot_mmap);
+
+ offset += num_mmaps * (uint32_t)sizeof(struct multiboot_mmap);
+
+ /* set the multiboot flags */
+ mbi->flags = MULTIBOOT_INFO_FLAG_HAS_CMDLINE | MULTIBOOT_INFO_FLAG_HAS_MODS
+ | MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS| MULTIBOOT_INFO_FLAG_HAS_MMAP;
+
+ for (uint32_t i = 0; i < num_mmaps; ++i) {
+ uint32_t parsed = sscanf(mmaps[i],"map%*[ \n\t]%" SCNx64
+ "%*[ \n\t]%" SCNx64 "%*[ \n\t]%" SCNu32,
+ &mbi_mmaps[i].base_addr,
+ &mbi_mmaps[i].length,
+ &mbi_mmaps[i].type);
+ if (parsed !=3) {
+ debug_printf("INVALID mmap: {%s}\n", mmaps[i]);
+ mbi_mmaps[i].size = 0;
+ continue;
+ }
+ mbi_mmaps[i].size = sizeof(struct multiboot_mmap);
}
- lvaddr_t image = 0;
- size_t imgsize = 0;
+ return sizeof(*mbi) + num_mods * sizeof(*mbi_mods) + num_mmaps * sizeof(*mbi_mmaps);
+}
- err = spawn_map_module(module, &imgsize, &image, NULL);
- if (err_is_fail(err)) {
- return err_push(err, SPAWN_ERR_ELF_MAP);
- }
+static errval_t download_modules_generic(struct xeon_phi *phi, size_t offset,
+ char **mods, uint32_t num_mods,
+ uint32_t num_mmaps, loadfile_fn_t loadfn,
+ size_t args)
+{
+ errval_t err;
- imgsize = module->mrmod_size;
+ struct xeon_phi_boot_params *bp;
+ bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
- XBOOT_DEBUG("loading multiboot image onto card... offset = 0x%lx\n",
- load_offset);
+ struct multiboot_info *mbi = (void *)phi->apt.vbase + offset;
+ struct multiboot_modinfo *mbi_mods = (struct multiboot_modinfo *)(mbi + 1);
- memcpy((void *) (phi->apt.vbase + load_offset), (void *) image, imgsize);
-#endif
+ bp->ramdisk_image = offset;
+ bp->mbi = offset;
- uint64_t imgsize;
+ offset += prepare_multiboot_info((void *)phi->apt.vbase, offset, mods + num_mods,
+ num_mods, num_mmaps);
- void *buf = (void *) (phi->apt.vbase + load_offset);
+ lpaddr_t strings_offset = offset;
+ offset += prepare_multiboot_strings((void *)phi->apt.vbase + strings_offset,
+ mods, num_mods);
- err = load_module(multiboot_img, phi->use_nfs, buf, &imgsize);
- if (err_is_fail(err)) {
- return err;
+ offset = ALIGN(offset);
+
+ for (uint32_t i = 0; i < num_mods; ++i) {
+ char *strings = (void *)phi->apt.vbase + strings_offset;
+ size_t cmdlength = strlen(strings);
+ size_t imgsize = 0;
+ mbi_mods[i].mod_start = offset;
+ mbi_mods[i].string = strings_offset;
+
+ char *delim = get_module_path(mods[i]);
+ *delim = 0;
+
+ err = loadfn(mods[i], (void *)phi->apt.vbase + offset, args, &imgsize);
+ if (err_is_fail(err)) {
+ return err;
+ }
+ mbi_mods[i].mod_end = mbi_mods[i].mod_start + imgsize;
+
+ offset = ALIGN(offset + imgsize);
+ strings_offset += (cmdlength + 1);
+
+ XBOOT_DEBUG("module %30s @ 0x08%lx size %lu kB\n",
+ (char *)phi->apt.vbase + strings_offset, offset, imgsize >> 10);
}
- /*
- * we are using the Linux style way in booting. The following will update
- * the corresponding fields in struct boot_param of the header.
- */
- struct xeon_phi_boot_params *bp;
- bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
- bp->ramdisk_image = (uint32_t)load_offset;
- bp->ramdisk_size = (uint32_t)imgsize;
+ bp->ramdisk_size = offset - bp->ramdisk_image;
return SYS_ERR_OK;
}
-/**
- * \brief generates the cmdline supplied to the card kernel
- *
- * \param phi the card information structure
- * \param load_offset offset where to load the cmdline
- * \param ret_size size of the cmdline in bytes
+
+static errval_t download_modules_vfs(struct xeon_phi *phi, size_t offset,
+ char **mods, uint32_t num_mods,
+ uint32_t num_mmaps, uint8_t use_nfs)
+{
+ return download_modules_generic(phi, offset, mods, num_mods, num_mmaps,
+ download_file_vfs, use_nfs);
+}
+
+static errval_t download_modules_tftp(struct xeon_phi *phi, lpaddr_t offset,
+ char **mods, uint32_t num_mods,
+ uint32_t num_mmaps)
+{
+ return download_modules_generic(phi, offset, mods, num_mods, num_mmaps,
+ tftp_client_read_file, TFTP_BUF_SIZE_MODULES);
+}
+
+/*
+ * -------------------------------------------------------------------------------
+ * Parsing modules
+ * -------------------------------------------------------------------------------
*/
-static errval_t load_cmdline(struct xeon_phi *phi,
- lvaddr_t load_offset)
+
+static inline char *discard_leading_white_spaces(char *string)
{
- uint32_t cmdlen = 0;
+ while(*string) {
+ if (!isspace((int)*string)) {
+ break;
+ }
+ string++;
+ }
+ return string;
+}
- struct xeon_phi_boot_params *bp;
- bp = (struct xeon_phi_boot_params *)(phi->apt.vbase + phi->os_offset);
- XBOOT_DEBUG("copying cmdline onto card, offset = 0x%lx\n", load_offset);
+static errval_t parse_mod_list(char *modules, uint32_t *mods, uint32_t *mmaps,
+ uint8_t *kernel, char ***parsed_modules)
+{
+ uint32_t num_mod = 0, num_mmap = 0;
+ uint8_t has_kernel = 0;
- void *buf = (void *) (phi->apt.vbase + load_offset);
+ char *line = modules;
- if (phi->cmdline) {
- cmdlen += sprintf(buf + cmdlen, "%s", phi->cmdline);
+ /* how many modules we have */
+ while (line != NULL)
+ {
+ if (*line == '\n') {
+ line++;
+ }
+ if (strncmp(line, "module", 6)==0) {
+ num_mod ++;
+ } else if (strncmp(line, "kernel", 6) == 0) {
+ assert(has_kernel == 0);
+ has_kernel = 1;
+ } else if (strncmp(line, "mmap", 4) == 0) {
+ num_mmap++;
+ }
+ line=strchr(line+1,'\n');
}
- cmdlen += sprintf(buf + cmdlen, "card_id=%i", phi->id);
- /*
- * id
- */
- /*
- * TODO: Add multihop / communication information here..
- */
+ /* allocate parsed array */
+ char **parsed = calloc(num_mod + num_mmap + 1, sizeof(char *));
+ if (parsed == NULL) {
+ return LIB_ERR_MALLOC_FAIL;
+ }
- printf("cmdline = %x, %s\n", (uint32_t)load_offset, (char*)buf);
+ uint32_t mod_idx = 1;
+ uint32_t mmap_idx = num_mod + num_mmap;
+ line = modules;
+ while (line != NULL)
+ {
+ if (*line == '\n') {
+ *line = 0;
+ line++;
+ }
+ if (strncmp(line, "module", 6)==0) {
+ parsed[mod_idx++] = discard_leading_white_spaces(line + 6);
+ } else if (strncmp(line, "kernel", 6) == 0) {
+ parsed[0] = discard_leading_white_spaces(line + 6);
+ } else if (strncmp(line, "mmap", 4) == 0) {
+ parsed[mmap_idx--] = discard_leading_white_spaces(line + 4);
+ }
+ line=strchr(line+1,'\n');
+ }
- phi->cmdline = buf;
- phi->cmdlen = cmdlen;
+ if (parsed_modules) {
+ *parsed_modules = parsed;
+ } else {
+ free(parsed_modules);
+ }
+ if (mods) {
+ *mods = num_mod;
+ }
- bp->cmdline_ptr = (uint32_t)(load_offset);
- bp->cmdline_size = (uint32_t)cmdlen;
+ if (mmaps) {
+ *mmaps = num_mmap;
+ }
+
+ if (kernel) {
+ *kernel = has_kernel;
+ }
+
+ XBOOT_DEBUG("parsing modules found: %u kernel, %u modules, %u mmaps\n",
+ has_kernel, num_mod, num_mmap);
return SYS_ERR_OK;
}
-static errval_t bootstrap_notify(struct xeon_phi *phi)
+
+static errval_t load_mod_list_tftp(char *mod_list, void **modules, size_t *size)
{
- // set the bootimage size to tell the bootloader
- xeon_phi_boot_os_size_rawwr(&boot_registers, phi->os_size);
+ errval_t err;
- uint64_t memsize = get_adapter_memsize();
+ void *buf = calloc(1, TFTP_BUF_SIZE);
- uint64_t reserved = (memsize * MEMORY_RESERVE_PERCENT / 100);
+ XBOOT_DEBUG("loading modules list %s over TFTP\n", mod_list);
- // Keep in mind maximum uos reserve size is uint32_t, so we never overflow
- reserved = MIN(reserved, UOS_RESERVE_SIZE_MAX);
- reserved = MAX(reserved, UOS_RESERVE_SIZE_MIN);
+ err = tftp_client_read_file(mod_list, buf, TFTP_BUF_SIZE, size);
+ if (err_is_fail(err)) {
+ USER_PANIC("reading tftp file");
+ }
- // Always align uos reserve size to a page
- reserved = (reserved & ~(BASE_PAGE_SIZE - 1));
+ if (modules) {
+ *modules = buf;
+ }
- xeon_phi_boot_res_size_rawwr(&boot_registers, (uint32_t) reserved);
+ return SYS_ERR_OK;
+}
- // sending the bootstrap interrupt
- xeon_phi_apic_icr_lo_t icr_lo = xeon_phi_apic_icr_lo_default;
- icr_lo = xeon_phi_apic_icr_lo_vector_insert(icr_lo, xeon_phi_apic_vec_bsp);
- icr_lo = xeon_phi_apic_icr_lo_boot_notify_insert(icr_lo, 0x1);
+static errval_t load_mod_list_vfs(char *mod_list, uint8_t use_nfs,
+ void **modules, size_t *size)
+{
+ errval_t err;
- assert(icr_lo == (229 | (1 << 13)));
+ XBOOT_DEBUG("loading modules list %s %s\n", mod_list,
+ (use_nfs==1 ? "over NFS" : "from ramfs"));
- xeon_phi_apic_icr_hi_wr(&apic_registers, xeon_phi_apic_bootstrap, phi->apicid);
+ /* load the menu lst file */
+ vfs_handle_t fh = file_open(mod_list, use_nfs);
+ if (fh == NULL) {
+ return SPAWN_ERR_LOAD;
+ }
- xeon_phi_apic_icr_lo_wr(&apic_registers, xeon_phi_apic_bootstrap, icr_lo);
+ struct vfs_fileinfo info;
+ err = vfs_stat(fh, &info);
+ if (err_is_fail(err)) {
+ vfs_close(fh);
+ return err_push(err, SPAWN_ERR_LOAD);
+ }
+
+ assert(info.type == VFS_FILE);
+
+ char *menulst = calloc(info.size + 1, 1);
+ if (menulst == NULL) {
+ vfs_close(fh);
+ return LIB_ERR_MALLOC_FAIL;
+ }
+
+ err = file_load(fh, menulst, info.size);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "file loading failed.\n");
+ vfs_close(fh);
+ free(menulst);
+ return err;
+ }
+
+ if (modules) {
+ *modules = menulst;
+ }
+
+ if (size) {
+ *size = info.size;
+ }
return SYS_ERR_OK;
}
* \brief boots the card with the given loader and multiboot image
*
* \param phi pointer to the card information
- * \param xloader_img pointer to the card bootloader image
- * \param multiboot_img pointer to the card multiboot image
+ * \param mod_uri name of to the modules location uri
+ * \param mod_list name of the modules list
*/
errval_t xeon_phi_boot(struct xeon_phi *phi,
- char *xloader_img,
- char *multiboot_img)
+ char *mod_uri,
+ char *mod_list)
{
errval_t err;
lvaddr_t offset;
phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);
- // load the coprocessor OS
- err = load_bootloader(phi, xloader_img);
+ void *modules = NULL;
+ size_t modules_size = 0;
+ uint8_t use_nfs = 0, use_tftp = 0;
+ if (strncmp(mod_uri, "nfs://", 6) == 0) {
+ XBOOT_DEBUG("using nfs share: %s\n", mod_uri);
+ use_nfs = 1;
+ err = load_mod_list_vfs(mod_list, 1, &modules, &modules_size);
+ } else if (strncmp(mod_uri, "tftp://", 7) == 0) {
+ use_tftp = 1;
+ char *del = strchr(mod_uri+7, ':');\
+ uint16_t port = 69; // default tftp port
+ if (del != NULL) {
+ port = atoi(del + 1);
+ *del = 0;
+ }
+
+ XBOOT_DEBUG("using tftp server: %s @ port %u\n", mod_uri + 7, port);
+
+ err = tftp_client_connect(mod_uri + 7, port);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "Could not connect to the tftp service");
+ }
+ err = load_mod_list_tftp(mod_list, &modules, &modules_size);
+ } else {
+ err = load_mod_list_vfs(mod_list, 0, &modules, &modules_size);
+ }
+
if (err_is_fail(err)) {
- USER_PANIC_ERR(err, "Could not load bootloader image");
+ USER_PANIC_ERR(err, "failed to load modules list");
}
- // round to next page
- offset = ALIGN(phi->os_offset + phi->os_size);
+ char **modules_parsed;
+ uint32_t num_mods, num_mmaps;
+ uint8_t has_kernel;
+ err = parse_mod_list(modules, &num_mods, &num_mmaps, &has_kernel, &modules_parsed);
+ if (err_is_fail(err)) {
+ return err;
+ }
- err = interphi_init(phi, NULL_CAP);
+ if (!has_kernel) {
+ return SPAWN_ERR_FIND_MODULE;
+ }
+
+ // load the coprocessor OS (boot loader)
+ if (use_tftp) {
+ err = download_bootloader_tftp(phi, modules_parsed[0]);
+ } else {
+ err = download_bootloader_vfs(phi, modules_parsed[0], use_nfs);
+ }
if (err_is_fail(err)) {
- USER_PANIC_ERR(err, "Could not initialize messaging");
+ USER_PANIC_ERR(err, "Could not load bootloader image");
}
+ // round to next page
+ offset = ALIGN(phi->os_offset + phi->os_size);
+
// load cmdline
err = load_cmdline(phi, offset);
if (err_is_fail(err)) {
// round to next page
offset = ALIGN(offset+phi->cmdlen);
- // load multiboot image
- err = load_multiboot_image(phi, multiboot_img, offset);
+ if (use_tftp) {
+ err = download_modules_tftp(phi, offset, modules_parsed + 1, num_mods, num_mmaps);
+ } else {
+ err = download_modules_vfs(phi, offset, modules_parsed + 1, num_mods, num_mmaps, use_nfs);
+ }
if (err_is_fail(err)) {
- USER_PANIC_ERR(err, "Could not load multiboot image");
+ USER_PANIC_ERR(err, "Could not load multiboot image");
+ }
+
+ free(modules_parsed);
+
+ if (use_tftp) {
+ tftp_client_disconnect();
}
struct xeon_phi_boot_params *bp;
bp->xeon_phi_id = 0xFF00;
bp->xeon_phi_id |= phi->id;
+ err = interphi_init(phi, NULL_CAP);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "Could not initialize messaging");
+ }
+
xeon_phi_boot_download_status_wrf(&boot_registers, 0x0);
phi->apicid = xeon_phi_boot_download_apicid_rdf(&boot_registers);