/*
 * Copyright (c) 2013 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "base/loader/dtb_file.hh"

#include <sys/mman.h>
#include <unistd.h>

#include <cassert>

#include "fdt.h"
#include "libfdt.h"
#include "sim/byteswap.hh"

namespace gem5
{

GEM5_DEPRECATED_NAMESPACE(Loader, loader);
namespace loader
{

DtbFile::DtbFile(const std::string &filename) :
    ImageFile(ImageFileDataPtr(new ImageFileData(filename)))
{
    panic_if(fdt_magic((const void *)imageData->data()) != FDT_MAGIC,
            "File %s doesn't seem to be a DTB.\n", filename);
    fileDataMmapped = true;
    fileData = const_cast<uint8_t *>(imageData->data());
    length = imageData->len();
}

DtbFile::~DtbFile()
{
    // Make sure to clean up memory properly depending
    // on how buffer was allocated.
    if (!fileDataMmapped)
        delete [] fileData;
}

bool
DtbFile::addBootData(const char *_cmdline, size_t cmdline_len,
                     off_t initrd_start, size_t initrd_len)
{
    const char *root_path = "/";
    const char *node_name = "chosen";
    const char *full_path_node_name = "/chosen";
    const char *bootargs_property_name = "bootargs";
    const char *linux_initrd_start_property_name = "linux,initrd-start";
    const char *linux_initrd_end_property_name = "linux,initrd-end";

    // Make a new buffer that has extra space to add nodes/properties
    int newLen = 2 * length;
    uint8_t *fdt_buf_w_space = new uint8_t[newLen];
    // Copy and unpack flattened device tree into new buffer
    int ret = fdt_open_into((void *)fileData, (void *)fdt_buf_w_space, newLen);
    if (ret < 0) {
        warn("Error resizing buffer of flattened device tree, "
             "errno: %d\n", ret);
        delete [] fdt_buf_w_space;
        return false;
    }

    // First try finding the /chosen node in the dtb
    int offset = fdt_path_offset((void *)fdt_buf_w_space, full_path_node_name);
    if (offset < 0) {
        // try adding the node by walking dtb tree to proper insertion point
        offset = fdt_path_offset((void *)fdt_buf_w_space, root_path);
        offset = fdt_add_subnode((void *)fdt_buf_w_space, offset, node_name);
        // if we successfully add the subnode, get the offset
        if (offset >= 0)
          offset = fdt_path_offset((void *)fdt_buf_w_space,
                                   full_path_node_name);

        if (offset < 0) {
            warn("Error finding or adding \"chosen\" subnode to flattened "
                 "device tree, errno: %d\n", offset);
            delete [] fdt_buf_w_space;
            return false;
        }
    }

    // Set the bootargs property in the /chosen node
    ret = fdt_setprop((void *)fdt_buf_w_space, offset, bootargs_property_name,
                      (const void *)_cmdline, cmdline_len+1);
    if (ret < 0) {
        warn("Error setting \"bootargs\" property to flattened device tree, "
             "errno: %d\n", ret);
        delete [] fdt_buf_w_space;
        return false;
    }

    if (initrd_len != 0) {
        // Set the linux,initrd-start property in the /chosen node
        ret = fdt_setprop_u64((void *)fdt_buf_w_space, offset,
                              linux_initrd_start_property_name,
                              (uint64_t)initrd_start);
        if (ret < 0) {
            warn("Error setting \"linux,initrd-start\" property to flattened "
                 "device tree, errno: %d\n", ret);
            delete [] fdt_buf_w_space;
            return false;
        }

        // Set the computed linux,initrd-end property in the /chosen node
        ret = fdt_setprop_u64((void *)fdt_buf_w_space, offset,
                              linux_initrd_end_property_name,
                              (uint64_t)initrd_start + initrd_len);
        if (ret < 0) {
            warn("Error setting \"linux,initrd-len\" property to flattened "
                 "device tree, errno: %d\n", ret);
            delete [] fdt_buf_w_space;
            return false;
        }
    }

    // Repack the dtb for kernel use
    ret = fdt_pack((void *)fdt_buf_w_space);
    if (ret < 0) {
        warn("Error re-packing flattened device tree structure, "
             "errno: %d\n", ret);
        delete [] fdt_buf_w_space;
        return false;
    }

    // clean up old buffer and set to new fdt blob
    if (!fileDataMmapped)
        delete [] fileData;
    fileData = fdt_buf_w_space;
    fileDataMmapped = false;
    length = newLen;

    return true;
}

Addr
DtbFile::findReleaseAddr()
{
    void *fd = (void *)fileData;

    int offset = fdt_path_offset(fd, "/cpus/cpu@0");
    int len;

    const void *temp = fdt_getprop(fd, offset, "cpu-release-addr", &len);
    Addr rel_addr = 0;

    if (len > 3)
        rel_addr = betoh(*static_cast<const uint32_t *>(temp));
    if (len == 8) {
        rel_addr = (rel_addr << 32) |
            betoh(*(static_cast<const uint32_t *>(temp) + 1));
    }

    return rel_addr;
}

MemoryImage
DtbFile::buildImage() const
{
    if (fileDataMmapped)
        return {{ "data", imageData }};
    else
        return {{ "data", 0, fileData, length }};
}

} // namespace loader
} // namespace gem5
