// Copyright 2014 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#include "android/base/containers/PodVector.h"
#include "android/base/Limits.h"
#include "android/base/Log.h"
#include "android/kernel/kernel_utils.h"
#include "android/kernel/kernel_utils_testing.h"
#include "android/utils/file_data.h"
#include "android/utils/path.h"
#include "android/utils/uncompress.h"

#include <algorithm>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#define DEBUG_KERNEL  0

#define KERNEL_LOG     LOG_IF(INFO, DEBUG_KERNEL)
#define KERNEL_PLOG    PLOG_IF(INFO, DEBUG_KERNEL)
#define KERNEL_ERROR   LOG_IF(ERROR, DEBUG_KERNEL)
#define KERNEL_PERROR  PLOG_IF(ERROR, DEBUG_KERNEL)

using android::base::PodVector;

namespace {

const char kLinuxVersionStringPrefix[] = "Linux version ";
const size_t kLinuxVersionStringPrefixLen =
        sizeof(kLinuxVersionStringPrefix) - 1U;

}  // namespace

#ifndef __APPLE__
size_t strlcpy(char* dst, const char * src, size_t size)
{
    size_t srcLen = strlen(src);
    if (size > 0) {
        size_t copyLen = std::min(srcLen, size-1);
        memcpy(dst, src, copyLen);
        dst[copyLen] = 0;
    }
    return srcLen;
}
#endif

#ifdef _WIN32
// TODO: (vharron) move somewhere more generally useful?
// Returns a pointer to the first occurrence of |needle| in |haystack|, or a 
// NULL pointer if |needle| is not part of |haystack|.
const void* memmem(const void* haystack, size_t haystackLen,
                   const void* needle, size_t needleLen) {
    if (needleLen == 0 ) {
        return haystack;
    }

    if (haystackLen < needleLen) {
        return NULL;
    }

    const char* haystackPos = (const char*)haystack;
    const char* haystackEnd = haystackPos + (haystackLen - needleLen);
    for (; haystackPos < haystackEnd; haystackPos++) {
        if (0==memcmp(haystackPos, needle, needleLen)) {
            return haystackPos;
        }
    }
    return NULL;
}
#endif


bool android_parseLinuxVersionString(const char* versionString,
                                     KernelVersion* kernelVersion) {
    if (strncmp(versionString, kLinuxVersionStringPrefix,
            kLinuxVersionStringPrefixLen)) {
        KERNEL_ERROR << "unsupported kernel version string:" << versionString;
        return false;
    }
    // skip past the prefix to the version number
    versionString += kLinuxVersionStringPrefixLen;

    uint32_t temp = 0;
    for (int i = 0; i < 3; i++) {
        // skip '.' delimeters
        while (i > 0 && *versionString == '.') {
            versionString++;
        }

        char* end;
        unsigned long number = ::strtoul(versionString, &end, 10);
        if (end == versionString || number > 0xff) {
            KERNEL_ERROR << "unsupported kernel version string:"
                         << versionString;
            return false;
        }
        temp <<= 8;
        temp |= number;
        versionString = end;
    }
    *kernelVersion = (KernelVersion)temp;

    KERNEL_LOG << android::base::LogString("Kernel version hex 0x%06x", temp);
    return true;
}

const char* android_kernelSerialDevicePrefix(KernelVersion kernelVersion) {
    if (kernelVersion >= KERNEL_VERSION_3_10_0) {
        return "ttyGF";
    }
    return "ttyS";
}

bool android_imageProbeKernelVersionString(const uint8_t* kernelFileData,
                                           size_t kernelFileSize,
                                           char* dst/*[dstLen]*/,
                                           size_t dstLen) {
    PodVector<uint8_t> uncompressed;

    const uint8_t* uncompressedKernel = NULL;
    size_t uncompressedKernelLen = 0;

    const char kElfHeader[] = { 0x7f, 'E', 'L', 'F' };

    if (kernelFileSize < sizeof(kElfHeader)) {
        KERNEL_ERROR << "Kernel image too short";
        return false;
    }

    const char* versionStringStart = NULL;

    if (0 == memcmp(kElfHeader, kernelFileData, sizeof(kElfHeader))) {
        // this is an uncompressed ELF file (probably mips)
        uncompressedKernel = kernelFileData;
        uncompressedKernelLen = kernelFileSize;
    }
    else {
        // handle compressed kernels here
        const uint8_t kGZipMagic[4] = { 0x1f, 0x8b, 0x08, 0x00 };
        const uint8_t* compressedKernel = (const uint8_t*)memmem(kernelFileData,
                                                                 kernelFileSize,
                                                                 kGZipMagic,
                                                                 sizeof(kGZipMagic));
        if (!compressedKernel) {
            KERNEL_ERROR << "Could not find gzip header in kernel file!";
            return false;
        }

        // Special case: certain images, like the ARM64 one, contain a GZip
        // header _after_ the actual Linux version string. So first try to
        // see if there is something before the header.
        versionStringStart = (const char*)memmem(
                kernelFileData,
                (compressedKernel - kernelFileData),
                kLinuxVersionStringPrefix,
                kLinuxVersionStringPrefixLen);

        if (!versionStringStart) {
            size_t compressedKernelLen = kernelFileSize -
                (compressedKernel - kernelFileData);

            // inflate ratios for all prebuilt kernels on 2014-07-14 is 1.9:1 ~
            // 3.43:1 not sure how big the uncompressed size is, so make an
            // absurdly large buffer
            uncompressedKernelLen = compressedKernelLen * 10;
            uncompressed.resize(uncompressedKernelLen);
            uncompressedKernel = uncompressed.begin();

            bool zOk = uncompress_gzipStream(uncompressed.begin(),
                                            &uncompressedKernelLen,
                                            compressedKernel,
                                            compressedKernelLen);
            if (!zOk) {
                KERNEL_ERROR << "Kernel decompression error";
                // it may have been partially decompressed, so we're going to
                // try to find the version string anyway
            }
        }
    }

    if (!versionStringStart) {
        versionStringStart = (const char*)memmem(
                uncompressedKernel,
                uncompressedKernelLen,
                kLinuxVersionStringPrefix,
                kLinuxVersionStringPrefixLen);

        if (!versionStringStart) {
            KERNEL_ERROR << "Could not find 'Linux version ' in kernel!";
            return false;
        }
    }

    strlcpy(dst, versionStringStart, dstLen);

    return true;
}

bool android_pathProbeKernelVersionString(const char* kernelPath,
                                          char* dst/*[dstLen]*/,
                                          size_t dstLen) {
    FileData kernelFileData;
    if (fileData_initFromFile(&kernelFileData, kernelPath) < 0) {
        KERNEL_ERROR << "Could not open kernel file!";
        return false;
    }

    return android_imageProbeKernelVersionString(kernelFileData.data,
                                                 kernelFileData.size,
                                                 dst,
                                                 dstLen);
}
