// Detect It Easy: detection rule file
// Author: LinXP
// doc-ref: https://source.denx.de/u-boot/u-boot/-/raw/e4dba4b/include/image.h

meta("format");

function detect() {
    if (Binary.getSize() >= 0x40) {
        if (Binary.compare("27051956")) { // Image Header Magic Number
            bDetected = true;

            sName = "U-Boot ";
            switch (Binary.readByte(0x1E)) { // Image Type
                case 0: sName += "Invalid Image"; break;
                case 1: sName += "Standalone Program"; break;
                case 2: sName += "OS Kernel Image"; break;
                case 3: sName += "RAMDisk Image"; break;
                case 4: sName += "Multi-File Image"; break;
                case 5: sName += "Firmware Image"; break;
                case 6: sName += "Script file"; break;
                case 7: sName += "Filesystem Image"; break;
                case 8: sName += "Binary Flat Device Tree Blob"; break;
                case 9: sName += "Kirkwood Boot Image"; break;
                case 10: sName += "Freescale IMXBoot Image"; break;
                case 11: sName += "Davinci UBL Image"; break;
                case 12: sName += "TI OMAP Config Header Image"; break;
                case 22: sName += "A list of typeless images"; break;
                case 23: sName += "Rockchip Boot Image"; break;
                case 24: sName += "Rockchip SD card"; break;
                case 25: sName += "Rockchip SPI image"; break;
                case 26: sName += "Xilinx Zynq Boot Image"; break;
                case 27: sName += "Xilinx ZynqMP Boot Image"; break;
                case 28: sName += "FPGA Image"; break;
                case 29: sName += "VYBRID .vyb Image"; break;
                case 30: sName += "Trusted Execution Environment OS Image"; break;
                case 31: sName += "Firmware Image with HABv4 IVT"; break;
                default: return;
            }
        }

        if (bDetected) {
            sVersion = "\"" + Binary.getString(0x20, 0x20) + "\""; // Image Name

            switch (Binary.readByte(0x1C)) { // Operating System
                case 0: sOptions = "Invalid OS"; break;
                case 1: sOptions = "OpenBSD"; break;
                case 2: sOptions = "NetBSD"; break;
                case 3: sOptions = "FreeBSD"; break;
                case 4: sOptions = "4.4BSD"; break;
                case 5: sOptions = "Linux"; break;
                case 6: sOptions = "SVR4"; break;
                case 7: sOptions = "Esix"; break;
                case 8: sOptions = "Solaris"; break;
                case 9: sOptions = "Irix"; break;
                case 10: sOptions = "SCO"; break;
                case 11: sOptions = "Dell"; break;
                case 12: sOptions = "NCR"; break;
                case 13: sOptions = "LynxOS"; break;
                case 14: sOptions = "VxWorks"; break;
                case 15: sOptions = "pSOS"; break;
                case 16: sOptions = "QNX"; break;
                case 17: sOptions = "Firmware"; break;
                case 18: sOptions = "RTEMS"; break;
                case 19: sOptions = "ARTOS"; break;
                case 20: sOptions = "Unity OS"; break;
                case 21: sOptions = "INTEGRITY"; break;
                case 22: sOptions = "OSE"; break;
                case 23: sOptions = "Plan 9"; break;
                case 24: sOptions = "OpenRTOS"; break;
                case 25: sOptions = "ARM Trusted Firmware"; break;
                case 26: sOptions = "Trusted Execution Environment"; break;
                case 27: sOptions = "RISC-V OpenSBI"; break;
                case 28: sOptions = "EFI Firmware"; break;
            }

            switch (Binary.readByte(0x1D)) { // CPU architecture
                case 0: sOptions = sOptions.append("Invalid CPU"); break;
                case 1: sOptions = sOptions.append("Alpha"); break;
                case 2: sOptions = sOptions.append("ARM"); break;
                case 3: sOptions = sOptions.append("Intel x86"); break;
                case 4: sOptions = sOptions.append("IA64"); break;
                case 5: sOptions = sOptions.append("MIPS"); break;
                case 6: sOptions = sOptions.append("MIPS64"); break;
                case 7: sOptions = sOptions.append("PowerPC"); break;
                case 8: sOptions = sOptions.append("IBM S390"); break;
                case 9: sOptions = sOptions.append("SuperH"); break;
                case 10: sOptions = sOptions.append("Sparc"); break;
                case 11: sOptions = sOptions.append("Sparc64"); break;
                case 12: sOptions = sOptions.append("M68K"); break;
                case 13: sOptions = sOptions.append("Nios-32"); break;
                case 14: sOptions = sOptions.append("MicroBlaze"); break;
                case 15: sOptions = sOptions.append("Nios-II"); break;
                case 16: sOptions = sOptions.append("Blackfin"); break;
                case 17: sOptions = sOptions.append("AVR32"); break;
                case 18: sOptions = sOptions.append("STM ST200"); break;
                case 19: sOptions = sOptions.append("Sandbox"); break;
                case 20: sOptions = sOptions.append("NDS32"); break;
                case 21: sOptions = sOptions.append("OpenRISC"); break;
                case 22: sOptions = sOptions.append("ARM64"); break;
                case 23: sOptions = sOptions.append("ARC"); break;
                case 24: sOptions = sOptions.append("AMD x86_64"); break;
                case 25: sOptions = sOptions.append("Xtensa"); break;
                case 26: sOptions = sOptions.append("RISC-V"); break;
            }

            switch (Binary.readByte(0x1F)) { // Compression Type
                case 0: sOptions = sOptions.append("no compression"); break;
                case 1: sOptions = sOptions.append("gzip"); break;
                case 2: sOptions = sOptions.append("bzip2"); break;
                case 3: sOptions = sOptions.append("lzma"); break;
                case 4: sOptions = sOptions.append("lzo"); break;
                case 5: sOptions = sOptions.append("lz4"); break;
                case 6: sOptions = sOptions.append("zstd"); break;
            }
        }
    }

    return result();
}