blob: 6812e3b87d0176b41271c5afb8d9e336ad999402 [file] [log] [blame]
// Copyright 2017 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 <assert.h>
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <string>
#include <vector>
#include <magenta/boot/bootdata.h>
#include "node.h"
#include "parser.h"
#include "tokens.h"
static bool run(std::vector<std::string>& in_paths, const char* out_path,
const char* header_path, bool debug) {
// root of our tree
Node root(mdi_root_id, "");
// iterate through our input files
for (auto iter = in_paths.begin(); iter != in_paths.end(); iter++) {
const char* in_path = iter->c_str();
if (!process_file(nullptr, in_path, root)) {
return false;
}
}
if (out_path) {
std::ofstream out_file;
out_file.open(out_path, std::ofstream::binary);
if (!out_file.good()) {
fprintf(stderr, "error: unable to open %s\n", out_path);
return false;
}
root.compute_node_length();
// write empty bootdata headers first
bootdata_t header;
memset(&header, 0, sizeof(header));
out_file.write((const char *)&header, sizeof(header));
out_file.write((const char *)&header, sizeof(header));
// write the nodes
root.serialize(out_file);
size_t total_len = out_file.tellp();
// back up and fill in the headers
out_file.seekp(0);
// Container header wraps the entire file
header.type = BOOTDATA_CONTAINER;
header.length = total_len - sizeof(header);
header.extra = BOOTDATA_MAGIC;
header.flags = 0;
out_file.write((const char *)&header, sizeof(header));
// MDI header around the MDI data
header.type = BOOTDATA_MDI;
header.length = total_len - 2 * sizeof(header);
header.extra = 0;
header.flags = 0;
out_file.write((const char *)&header, sizeof(header));
}
if (header_path) {
std::ofstream header_file;
header_file.open(header_path, std::ofstream::binary);
if (!header_file.good()) {
fprintf(stderr, "error: unable to open %s\n", header_path);
return false;
}
print_header_file(header_file);
}
if (debug) {
// print parse tree
root.print();
}
return true;
}
static void usage() {
fprintf(stderr, "uasge: mdigen <input files> -o <output file> -h <C header output file>\n"
"Additional options:\n"
"\t-d - debug output, prints parse tree\n"
"\t-p <prefix> - prefix for symbols in C header file\n"
"\t-u - convert symbols in C header file to upper case\n");
}
int main(int argc, char* argv[]) {
std::vector<std::string> in_paths;
const char* out_path = nullptr;
const char* header_path = nullptr;
bool debug = false;
argc--;
argv++;
if (argc == 0) {
usage();
return -1;
}
while (argc > 0) {
const char *arg = argv[0];
if (arg[0] != '-') {
in_paths.push_back(arg);
} else if (!strcmp(arg, "-o") && argc >= 2) {
out_path = argv[1];
argc--;
argv++;
} else if (!strcmp(arg, "-h") && argc >= 2) {
header_path = argv[1];
argc--;
argv++;
} else if (!strcmp(arg, "-d")) {
debug = true;
} else {
fprintf(stderr, "unknown argument \"%s\"\n", arg);
usage();
return -1;
}
argc--;
argv++;
}
if (in_paths.size() == 0) {
fprintf(stderr, "no input files specified\n");
usage();
return -1;
}
bool result = run(in_paths, out_path, header_path, debug);
return (result ? 0 : -1);
}