Skip to content

Commit

Permalink
# new implementation of x86 instruction parser
Browse files Browse the repository at this point in the history
  • Loading branch information
tommojphillips committed Jul 6, 2024
1 parent 5880dd1 commit b8794f1
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 40 deletions.
2 changes: 1 addition & 1 deletion inc/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define XB_BIOS_TOOL_VER_MAJOR 0
#define XB_BIOS_TOOL_VER_MINOR 1
#define XB_BIOS_TOOL_VER_PATCH 0
#define XB_BIOS_TOOL_VER_BUILD 6
#define XB_BIOS_TOOL_VER_BUILD 7

#define XB_BIOS_TOOL_AUTHOR_STR "tommojphillips"
#define XB_BIOS_TOOL_NAME_STR "XbTool"
Expand Down
76 changes: 38 additions & 38 deletions src/Bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "lzx.h"
#include "sha1.h"

extern XbTool xbtool;
extern Parameters& params;

void Bios::reset()
{
Expand Down Expand Up @@ -114,7 +114,7 @@ void Bios::getOffsets2(const UINT krnlSize, const UINT krnlDataSize)
krnl = (krnlData - krnlSize);

// calculate the total space available in the rom.
_totalSpaceAvailable = xbtool.params.romsize - BLDR_BLOCK_SIZE - MCPX_BLOCK_SIZE;
_totalSpaceAvailable = params.romsize - BLDR_BLOCK_SIZE - MCPX_BLOCK_SIZE;

// calculate the available space in the bios.
_availableSpace = _totalSpaceAvailable - krnlSize - krnlDataSize;
Expand Down Expand Up @@ -148,13 +148,13 @@ int Bios::checkForPreldr()

print("\npreldr found\n");

if (xbtool.params.mcpx.data == NULL)
if (params.mcpx.data == NULL)
{
error("Error: MCPX v1.1 rom is required to decrypt the preldr ( -mcpx )\n");
return PRELDR_STATUS_ERROR;
}

if (xbtool.params.mcpx.version != MCPX_ROM::MCPX_V1_1)
if (params.mcpx.version != MCPX_ROM::MCPX_V1_1)
{
// user has provided the incorrect mcpx rom. let 'em know.
error("Error: decrypting the bldr. MCPX v1.1 was expected but v1.0 was provided.\n");
Expand All @@ -163,7 +163,7 @@ int Bios::checkForPreldr()

PRELDR_ENTRY* preldrEntry = (PRELDR_ENTRY*)(preldr + (preldrParams->jmpInstr >> 8) + 0x5 - sizeof(PRELDR_ENTRY));

UCHAR* sbKey = (UCHAR*)(xbtool.params.mcpx.data + MCPX_BLOCK_SIZE - 0x64);
UCHAR* sbKey = (UCHAR*)(params.mcpx.data + MCPX_BLOCK_SIZE - 0x64);

#if 0
// decrypt the preldr pubkey
Expand Down Expand Up @@ -234,8 +234,8 @@ int Bios::load(UCHAR* data, const UINT size)
_size = size;

// set encryption states based on user input.
_isBldrEncrypted = xbtool.params.encBldr;
_isKernelEncrypted = xbtool.params.encKrnl;
_isBldrEncrypted = params.encBldr;
_isKernelEncrypted = params.encKrnl;

getOffsets();

Expand All @@ -246,16 +246,16 @@ int Bios::load(UCHAR* data, const UINT size)
// only decrypt the bldr if the user has provided a key file or a mcpx rom and the bldr is encrypted.
if (_isBldrEncrypted)
{
if (xbtool.params.keyBldr != NULL) // bldr key is provided; use it.
if (params.keyBldr != NULL) // bldr key is provided; use it.
{
symmetricEncDecBldr(xbtool.params.keyBldr, KEY_SIZE);
symmetricEncDecBldr(params.keyBldr, KEY_SIZE);
}
else if (xbtool.params.mcpxFile != NULL)
else if (params.mcpxFile != NULL)
{
switch (xbtool.params.mcpx.version)
switch (params.mcpx.version)
{
case MCPX_ROM::MCPX_V1_0:
symmetricEncDecBldr(xbtool.params.mcpx.data+0x1A5, KEY_SIZE);
symmetricEncDecBldr(params.mcpx.data+0x1A5, KEY_SIZE);
break;
case MCPX_ROM::MCPX_V1_1:
error("Error: decrypting the bldr. MCPX v1.0 was expected but v1.1 was provided.\n");
Expand Down Expand Up @@ -329,31 +329,31 @@ int Bios::saveBiosToFile(const char* path)
return 1;
}

if (xbtool.params.binsize < _size)
if (params.binsize < _size)
{
error("Error: Desired bin size is less than the total size of the bios\n");
return 1;
}

// replicate up to 1Mb

UCHAR* biosData = (UCHAR*)xb_alloc(xbtool.params.binsize);
UCHAR* biosData = (UCHAR*)xb_alloc(params.binsize);

xb_cpy(biosData, _bios, _size); // copy the bios data

// replicate to 512 KB
if (_size < 0x80000 && xbtool.params.binsize >= 0x80000)
if (_size < 0x80000 && params.binsize >= 0x80000)
{
xb_cpy(biosData + 0x40000, biosData, _size);
}

// replicate to 1 MB
if (_size < 0x100000 && xbtool.params.binsize >= 0x100000)
if (_size < 0x100000 && params.binsize >= 0x100000)
{
xb_cpy(biosData + 0x80000, biosData, 0x80000);
}

int result = writeFile(path, biosData, xbtool.params.binsize);
int result = writeFile(path, biosData, params.binsize);

xb_free(biosData);

Expand Down Expand Up @@ -429,7 +429,7 @@ void Bios::symmetricEncDecKernel()
if (krnl == NULL)
return;

UCHAR* key = xbtool.params.keyKrnl;
UCHAR* key = params.keyKrnl;
if (key == NULL)
{
// key not provided on cli; try get key from bldr block.
Expand Down Expand Up @@ -490,8 +490,8 @@ void Bios::printBldrInfo()
UINT krnlSize = bootParams->krnlSize;
UINT krnlDataSize = bootParams->krnlDataSize;

bool isKrnlSizeValid = krnlSize >= 0 && krnlSize <= xbtool.params.romsize;
bool isKrnlDataSizeValid = krnlDataSize >= 0 && krnlDataSize <= xbtool.params.romsize;
bool isKrnlSizeValid = krnlSize >= 0 && krnlSize <= params.romsize;
bool isKrnlDataSizeValid = krnlDataSize >= 0 && krnlDataSize <= params.romsize;

print("kernel data size:\t");
print((CON_COL)isKrnlDataSizeValid, "%ld", krnlDataSize);
Expand Down Expand Up @@ -583,7 +583,7 @@ void Bios::printInitTblInfo()
print(" ( %04x )\nRevision:\t\trev %d.%02d\n", initTbl->init_tbl_identifier, initTbl->revision >> 8, initTbl->revision & 0xFF);

UINT initTblSize = bootParams->inittblSize;
bool isInitTblSizeValid = initTblSize >= 0 && initTblSize <= xbtool.params.romsize;
bool isInitTblSizeValid = initTblSize >= 0 && initTblSize <= params.romsize;

print("Size:\t\t\t");
print((CON_COL)isInitTblSizeValid, "%ld", initTblSize);
Expand Down Expand Up @@ -729,7 +729,7 @@ int Bios::validateBldr()
const UINT krnlDataSize = bootParams->krnlDataSize;
const UINT tblSize = bootParams->inittblSize;
const UINT availableSpace = _totalSpaceAvailable;
const UINT romSize = xbtool.params.romsize;
const UINT romSize = params.romsize;

const bool isKrnlSizeValid = krnlSize >= 0 && krnlSize <= romSize;
const bool isDataSizeValid = krnlDataSize >= 0 && krnlDataSize <= romSize;
Expand Down Expand Up @@ -791,25 +791,25 @@ int Bios::create(UCHAR* in_bl, UINT in_blSize, UCHAR* in_tbl, UINT in_tblSize, U
}

// check romsize is big enough for the bios.
if (xbtool.params.romsize < in_tblSize + BLDR_BLOCK_SIZE + MCPX_BLOCK_SIZE + in_kSize + in_kDataSize)
if (params.romsize < in_tblSize + BLDR_BLOCK_SIZE + MCPX_BLOCK_SIZE + in_kSize + in_kDataSize)
{
error("Error: romsize is less than the total size of the bios\n");
return BIOS_LOAD_STATUS_FAILED;
}

_bios = (UCHAR*)xb_alloc(xbtool.params.romsize);
_bios = (UCHAR*)xb_alloc(params.romsize);
if (_bios == NULL)
{
error("Error: Failed to allocate memory\n");
return BIOS_LOAD_STATUS_FAILED;
}
_size = xbtool.params.romsize;
_size = params.romsize;

// set encryption states based on user input.
// when building a bios. the bldr file, and kernel file is expected to be passed in UNENCRYPTED.
// This is because a bios can't be extracted unless the 2bl is decrypted.
_isBldrEncrypted = !xbtool.params.encBldr;
_isKernelEncrypted = !xbtool.params.encKrnl;
_isBldrEncrypted = !params.encBldr;
_isKernelEncrypted = !params.encKrnl;

getOffsets();

Expand Down Expand Up @@ -849,32 +849,32 @@ int Bios::create(UCHAR* in_bl, UINT in_blSize, UCHAR* in_tbl, UINT in_tblSize, U
{
// kernel was encrypted successfully. update the kernel key in the bldr.

if (bldrKeys != NULL && xbtool.params.keyKrnl != NULL)
if (bldrKeys != NULL && params.keyKrnl != NULL)
{
print("Updating kernel key in bldr..\n");
xb_cpy(bldrKeys->krnlKey, xbtool.params.keyKrnl, KEY_SIZE);
xb_cpy(bldrKeys->krnlKey, params.keyKrnl, KEY_SIZE);
}
}
}

if ((xbtool.params.sw_flag & SW_BLD_BFM) != 0) // build a bios that boots from media.
if ((params.sw_flag & SW_BLD_BFM) != 0) // build a bios that boots from media.
{
convertToBootFromMedia();
}

// only encrypt the bldr if the user has provided a key file or a mcpx rom and the bldr is not already encrypted.
if (!_isBldrEncrypted)
{
if (xbtool.params.keyBldr != NULL)
if (params.keyBldr != NULL)
{
symmetricEncDecBldr(xbtool.params.keyBldr, KEY_SIZE);
symmetricEncDecBldr(params.keyBldr, KEY_SIZE);
}
else if (xbtool.params.mcpxFile != NULL)
else if (params.mcpxFile != NULL)
{
switch (xbtool.params.mcpx.version)
switch (params.mcpx.version)
{
case MCPX_ROM::MCPX_V1_0:
symmetricEncDecBldr(xbtool.params.mcpx.data+0x1A5, KEY_SIZE);
symmetricEncDecBldr(params.mcpx.data+0x1A5, KEY_SIZE);
break;
case MCPX_ROM::MCPX_V1_1:
break;
Expand Down Expand Up @@ -904,7 +904,7 @@ int Bios::convertToBootFromMedia()

// encrypt the bldr with the bfm key.

if (xbtool.params.keyBldr == NULL)
if (params.keyBldr == NULL)
{
if (bldrKeys == NULL)
{
Expand All @@ -918,7 +918,7 @@ int Bios::convertToBootFromMedia()
}
else
{
if (xb_cmp(xbtool.params.keyBldr, bldrKeys->bfmKey, KEY_SIZE) != 0)
if (xb_cmp(params.keyBldr, bldrKeys->bfmKey, KEY_SIZE) != 0)
{
error("Error: BFM key does not match the key in the bldr\n");
return 1;
Expand All @@ -927,7 +927,7 @@ int Bios::convertToBootFromMedia()
}

// force the bfm bios to be 1Mb in size.
xbtool.params.binsize = 1 * 1024 * 1024; // 1Mb
params.binsize = 1 * 1024 * 1024; // 1Mb

return 0;
}
91 changes: 90 additions & 1 deletion src/XcodeInterp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,58 @@ int XcodeInterp::decodeXcodes()
return 0;
}

//#define XCODE_SIM_OLD_CODE 0

int XcodeInterp::simulateXcodes()
{
// load the inittbl file

#ifndef XCODE_SIM_OLD_CODE
typedef struct X86_INSTR
{
USHORT opcode;
const char* asm_instr;
UINT opcode_len;
UINT instr_len;
bool uses_operand = false;
const char* data_str = NULL;
} X86_INSTR;

const char* PTR_DATA_STR = ", [0x%08x]";
const char* NUM_DATA_STR = ", 0x%08x";

const X86_INSTR instrs[] = {
{ 0x1D8B, "mov ebx", 2, 6, true, PTR_DATA_STR },
{ 0x0D8B, "mov ecx", 2, 6, true, PTR_DATA_STR },
{ 0x158B, "mov edx", 2, 6, true, PTR_DATA_STR },

{ 0xE0FF, "jmp eax", 2, 2 },
{ 0xE1FF, "jmp ecx", 2, 2 },
{ 0xE2FF, "jmp edx", 2, 2 },
{ 0xE3FF, "jmp ebx", 2, 2 },
{ 0xE4FF, "jmp esp", 2, 2 },
{ 0xE5FF, "jmp ebp", 2, 2 },
{ 0xE6FF, "jmp esi", 2, 2 },
{ 0xE7FF, "jmp edi", 2, 2 },

{ 0xA5F3, "rep movsd", 2, 2 },

{ 0xB8, "mov eax", 1, 5, true },
{ 0xB9, "mov ecx", 1, 5, true },
{ 0xBA, "mov edx", 1, 5, true },
{ 0xBB, "mov ebx", 1, 5, true },
{ 0xBC, "mov esp", 1, 5, true },
{ 0xBD, "mov ebp", 1, 5, true },
{ 0xBE, "mov esi", 1, 5, true },
{ 0xBF, "mov edi", 1, 5, true },
{ 0xA1, "mov eax", 1, 5, true, PTR_DATA_STR },

{ 0xEA, "jmp far", 1, 6, true },
{ 0x90, "nop", 1, 1 },
{ 0xFC, "cld", 1, 1 }
};

#else
// 6 byte encoding
const USHORT MOV_PTR_INSTRS_2_BYTE[] = { 0x1D8B, 0x0D8B, 0x158B };
const char* MOV_PTR_NAMES_2_BYTE[] = { "mov ebx", "mov ecx", "mov edx" };
Expand Down Expand Up @@ -438,13 +486,19 @@ int XcodeInterp::simulateXcodes()
// 1 byte encoding
const UCHAR CLD_INSTR = 0xFC;
const char* CLD_NAME = "cld";
#endif

const UINT DEFAULT_SIM_SIZE = 128; // 32KB
const UINT DEFAULT_SIM_SIZE = 32; // 32KB
const UINT SIM_SIZE = (params.simSize > 0) ? params.simSize : DEFAULT_SIM_SIZE;

const UINT MAX_INSTR_SIZE = 6;
const UCHAR zero_mem[MAX_INSTR_SIZE] = { 0 };
char str_opcode[16] = { 0 };
char str_operand[16] = { 0 };
char str_instr[32] = { 0 };

UINT operand = 0;
UINT operandLen = 0;

int result = 0;

Expand Down Expand Up @@ -517,6 +571,40 @@ int XcodeInterp::simulateXcodes()
if (xb_cmp(mem_sim + i, zero_mem, (i < SIM_SIZE - MAX_INSTR_SIZE ? MAX_INSTR_SIZE : SIM_SIZE - i)) == 0)
break;

#ifndef XCODE_SIM_OLD_CODE
// iterate through the x86 instructions
for (j = 0; j < sizeof(instrs) / sizeof(X86_INSTR); j++)
{
if (xb_cmp(mem_sim + i, (UCHAR*)&instrs[j].opcode, instrs[j].opcode_len) == 0)
{
xb_zero(str_instr, sizeof(str_instr));
format(str_instr, "%04x: %s", i, instrs[j].asm_instr);

if (instrs[j].uses_operand)
{
operand = 0;
operandLen = instrs[j].instr_len - instrs[j].opcode_len;
if (operandLen > 4) // UINT is 4 bytes
operandLen = 4;

// to-do: fix jmp far operand. currently only supports 4 byte operand single operand instructions.

xb_cpy(&operand, (UCHAR*)(mem_sim + i + instrs[j].opcode_len), operandLen);
format(str_operand, instrs[j].data_str == NULL ? NUM_DATA_STR : instrs[j].data_str, operand);
strcat(str_instr, str_operand);
}
strcat(str_instr, "\n");

print(str_instr);

i += instrs[j].instr_len;
found = true;
break;
}
}
if (found)
continue;
#else
found = false;

// check for 2 byte mov ptr instructions
Expand Down Expand Up @@ -604,6 +692,7 @@ int XcodeInterp::simulateXcodes()
i++; // 1 byte opcode
continue;
}
#endif

// opcode not found
error("Error: Unknown instruction at offset %04x, INSTR: %02X\n", i, mem_sim[i]);
Expand Down

0 comments on commit b8794f1

Please sign in to comment.