173 lines
5.1 KiB
C++
173 lines
5.1 KiB
C++
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: mkcore.cpp
|
||
|
//
|
||
|
// Contents: Creates a core file from one or more PE image by physically
|
||
|
// aligning and allocating all of the sections.
|
||
|
//
|
||
|
#define UNICODE
|
||
|
#define _UNICODE
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stddef.h>
|
||
|
#include <winlean.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
typedef signed int INT;
|
||
|
typedef signed char INT8, *LPINT8;
|
||
|
typedef signed short INT16, *LPINT16;
|
||
|
typedef unsigned int UINT;
|
||
|
typedef unsigned char UINT8, *LPUINT8;
|
||
|
typedef unsigned short UINT16, *LPUINT16;
|
||
|
|
||
|
UINT32 to_arm(UINT32 value)
|
||
|
{
|
||
|
return (((value & 0xff000000) >> 24) |
|
||
|
((value & 0x00ff0000) >> 8) |
|
||
|
((value & 0x0000ff00) << 8) |
|
||
|
((value & 0x000000ff) << 24));
|
||
|
}
|
||
|
|
||
|
BOOL MakeRaw(PCWSTR pwzImage)
|
||
|
{
|
||
|
HANDLE hFile = CreateFile(pwzImage,
|
||
|
GENERIC_READ | GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
NULL);
|
||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||
|
fprintf(stderr, "Could not open image file: %ls\n", pwzImage);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ULONG cbInFileData = GetFileSize(hFile, NULL);
|
||
|
if (cbInFileData == 0xffffffff) {
|
||
|
CloseHandle(hFile);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DWORD dwRead = 0;
|
||
|
|
||
|
// Read the DOS header.
|
||
|
//
|
||
|
IMAGE_DOS_HEADER idh;
|
||
|
IMAGE_NT_HEADERS inh;
|
||
|
|
||
|
if (!ReadFile(hFile, &idh, sizeof(idh), &dwRead, NULL) || dwRead != sizeof(idh)) {
|
||
|
failed:
|
||
|
fprintf(stderr, "Invalid image: %ls\n", pwzImage);
|
||
|
CloseHandle(hFile);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (idh.e_magic != IMAGE_DOS_SIGNATURE) {
|
||
|
goto failed;
|
||
|
}
|
||
|
|
||
|
// Read in the PE image header
|
||
|
//
|
||
|
if (SetFilePointer(hFile, idh.e_lfanew, NULL, FILE_BEGIN) != idh.e_lfanew) {
|
||
|
goto failed;
|
||
|
}
|
||
|
if (!ReadFile(hFile, &inh, sizeof(inh), &dwRead, NULL) || dwRead != sizeof(inh)) {
|
||
|
goto failed;
|
||
|
}
|
||
|
if (inh.Signature != IMAGE_NT_SIGNATURE) {
|
||
|
goto failed;
|
||
|
}
|
||
|
if (inh.FileHeader.Machine != IMAGE_FILE_MACHINE_ARM &&
|
||
|
inh.FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB) {
|
||
|
fprintf(stderr, "mkarmraw: machine: %04x!\n");
|
||
|
}
|
||
|
|
||
|
if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
|
||
|
goto failed;
|
||
|
}
|
||
|
|
||
|
// To make a raw binary (i.e. one that starts with valid ARM instructions),
|
||
|
// we need to insert a branch to the PE entry point. However, we want
|
||
|
// the file to still look like a valid PE binary, so it needs to start with
|
||
|
// the ascii value "MZ". So, we place an innocent orr instruction, which
|
||
|
// coincidentally has "MZ" as its first two bytes, at the start of the file
|
||
|
// followed by a branch to the entry point.
|
||
|
//
|
||
|
UINT32 offset = inh.OptionalHeader.AddressOfEntryPoint - 12;
|
||
|
UINT32 val = 0x63855a4d; // orrvs r5, r5, #0x4d, 20. aka MZ nop
|
||
|
if (!WriteFile(hFile, &val, sizeof(val), &dwRead, NULL) || dwRead != sizeof(val)) {
|
||
|
goto failed;
|
||
|
}
|
||
|
val = 0xea000000 | (offset >> 2); // ea = B offset
|
||
|
if (!WriteFile(hFile, &val, sizeof(val), &dwRead, NULL) || dwRead != sizeof(val)) {
|
||
|
goto failed;
|
||
|
}
|
||
|
|
||
|
CloseHandle(hFile);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
int __cdecl wmain(int argc, WCHAR **argv)
|
||
|
{
|
||
|
BOOL fNeedHelp = FALSE;
|
||
|
|
||
|
for (int arg = 1; arg < argc && !fNeedHelp; arg++) {
|
||
|
if (argv[arg][0] == '-' || argv[arg][0] == '/') {
|
||
|
WCHAR *argn = argv[arg]+1; // Argument name
|
||
|
WCHAR *argp = argn; // Argument parameter
|
||
|
|
||
|
while (*argp && *argp != ':') {
|
||
|
argp++;
|
||
|
}
|
||
|
if (*argp == ':')
|
||
|
*argp++ = '\0';
|
||
|
|
||
|
switch (argn[0]) {
|
||
|
|
||
|
case '?': // Help
|
||
|
fNeedHelp = TRUE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("Unknown argument: %ls\n", argv[arg]);
|
||
|
fNeedHelp = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!MakeRaw(argv[arg])) {
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (argc == 1) {
|
||
|
fNeedHelp = TRUE;
|
||
|
}
|
||
|
|
||
|
if (fNeedHelp) {
|
||
|
printf(
|
||
|
"Usage:\n"
|
||
|
" mkarmraw [options] images...\n"
|
||
|
"Options:\n"
|
||
|
" /? -- Display this help screen.\n"
|
||
|
"Summary:\n"
|
||
|
" Converts a 512-byte aligned PE image into a raw ARM boot file.\n"
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////// End of File.
|