704 lines
14 KiB
C
704 lines
14 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
acpiload.c
|
|
|
|
Abstract:
|
|
|
|
This program installs an AML file into the NT registry
|
|
|
|
Author:
|
|
|
|
Ken Reneris
|
|
|
|
Environment:
|
|
|
|
Command-line.
|
|
|
|
Revision History:
|
|
|
|
2-23-2000 - mmurph - Added support for images besides DSDTs
|
|
2-23-2000 - mmurph - Added support to force load for unknown image type
|
|
|
|
--*/
|
|
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <amlreg.h>
|
|
//#include <varargs.h>
|
|
|
|
#define SIGNATURES {'TDSD', 'TDSR', 'TDSS', 'TDSP', 'CIPA', 'PCAF', 'SCAF', 'TSBS'}
|
|
|
|
#define DATA_SIZE 7*1024 // max value to write into registry
|
|
|
|
typedef struct {
|
|
ULONG Signature;
|
|
ULONG Length;
|
|
UCHAR Revision;
|
|
UCHAR Checksum;
|
|
UCHAR OemID[6];
|
|
UCHAR OemTableID[8];
|
|
ULONG OemRevision;
|
|
UCHAR CreatorID[4];
|
|
UCHAR CreatorRevision[4];
|
|
} DSDT, *PDSDT;
|
|
|
|
|
|
IFILE Update; // Image of updated aml file
|
|
IFILE Orig; // Image of original aml file
|
|
BOOLEAN Verbose;
|
|
BOOLEAN DeleteUpdate;
|
|
BOOLEAN Force;
|
|
BOOLEAN ArgsParsed;
|
|
BOOLEAN RegInProgress;
|
|
HKEY RegKey;
|
|
|
|
ULONG RegDataSequence;
|
|
ULONG RegDataSize;
|
|
UCHAR RegDataBuffer[DATA_SIZE];
|
|
UCHAR s[500]; // Registry path
|
|
PUCHAR signa;
|
|
|
|
//
|
|
// Internal prototypes
|
|
//
|
|
|
|
VOID
|
|
ParseArgs (
|
|
IN int argc,
|
|
IN char *argv[]
|
|
);
|
|
|
|
VOID
|
|
CheckImageHeader (
|
|
IN PIFILE File
|
|
);
|
|
|
|
VOID
|
|
GetRegistryKey (
|
|
IN PIFILE Image
|
|
);
|
|
|
|
VOID
|
|
FAbort (
|
|
PUCHAR Text,
|
|
PIFILE File
|
|
);
|
|
|
|
VOID
|
|
Abort (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
BuildUpdate (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
AddRun (
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
);
|
|
|
|
VOID
|
|
FlushRun (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
DeleteRegistryNode (
|
|
IN HKEY Handle
|
|
);
|
|
|
|
PUCHAR
|
|
FixString (
|
|
IN PUCHAR Str,
|
|
IN ULONG Len
|
|
);
|
|
|
|
int
|
|
__cdecl
|
|
main(
|
|
IN int argc,
|
|
IN char *argv[]
|
|
) {
|
|
//
|
|
// Init globals
|
|
//
|
|
|
|
Update.Desc = "update image";
|
|
Orig.Desc = "original image";
|
|
|
|
//
|
|
// Parse args
|
|
//
|
|
|
|
ParseArgs(argc, argv);
|
|
|
|
//
|
|
// Parse image headers
|
|
//
|
|
|
|
CheckImageHeader (&Update);
|
|
if (Orig.Opened) {
|
|
CheckImageHeader (&Orig);
|
|
|
|
// verify oem info
|
|
if (strcmp (Update.OemID, Orig.OemID)) {
|
|
printf ("OEM id in update image mis-matches original image\n");
|
|
Abort ();
|
|
}
|
|
|
|
if (strcmp (Update.OemTableID, Orig.OemTableID)) {
|
|
printf ("OEM table id in update image mis-matches original image\n");
|
|
Abort ();
|
|
}
|
|
|
|
if (Update.OemRevision != Orig.OemRevision) {
|
|
printf ("OEM revision in update image revision does not match\n");
|
|
Abort ();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Open/create proper registry location
|
|
//
|
|
|
|
GetRegistryKey (&Update);
|
|
|
|
//
|
|
// Delete any existing stuff
|
|
//
|
|
|
|
DeleteRegistryNode (RegKey);
|
|
if (DeleteUpdate) {
|
|
printf ("Registry data deleted\n");
|
|
exit (1);
|
|
}
|
|
|
|
//
|
|
// For now hardcoded to "update" action
|
|
//
|
|
BuildUpdate ();
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID
|
|
BuildUpdate (
|
|
VOID
|
|
) {
|
|
LONG Status;
|
|
ULONG i, Len, Offs, RunLen, match;
|
|
|
|
RegDataSequence = 0;
|
|
RegDataSize = 0;
|
|
RegInProgress = TRUE;
|
|
|
|
//
|
|
// If there's no original image, just write the new one
|
|
//
|
|
|
|
if (!Orig.Opened) {
|
|
AddRun (Update.FileSize, 0);
|
|
AddRun (0, Update.FileSize);
|
|
} else {
|
|
if (Update.FileSize != Orig.FileSize) {
|
|
AddRun (Update.FileSize, 0);
|
|
}
|
|
|
|
Len = Update.FileSize;
|
|
if (Orig.FileSize < Update.FileSize) {
|
|
Len = Orig.FileSize;
|
|
}
|
|
|
|
Offs=0;
|
|
while (Offs < Len) {
|
|
//
|
|
// Skip matching bytes
|
|
//
|
|
if (Update.Image[Offs] == Orig.Image[Offs]) {
|
|
Offs += 1;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Count mismatching bytes
|
|
//
|
|
match = 0;
|
|
for (RunLen=1; Offs+RunLen < Len; RunLen++) {
|
|
if (Update.Image[Offs+RunLen] == Orig.Image[Offs+RunLen]) {
|
|
match += 1;
|
|
if (match > 8) {
|
|
break;
|
|
}
|
|
} else {
|
|
match = 0;
|
|
}
|
|
}
|
|
|
|
RunLen -= match;
|
|
AddRun (Offs, RunLen);
|
|
Offs += RunLen;
|
|
}
|
|
|
|
//
|
|
// If there's more at the end add it
|
|
//
|
|
|
|
if (Len < Update.FileSize) {
|
|
AddRun (Len, Update.FileSize - Len);
|
|
}
|
|
|
|
}
|
|
|
|
FlushRun();
|
|
if (RegDataSequence) {
|
|
if (Verbose) {
|
|
printf ("SetValue Action\n");
|
|
}
|
|
|
|
i = 0; // BUGBUG: values need defined
|
|
Status = RegSetValueEx (RegKey, "Action", 0L, REG_DWORD,(PUCHAR) &i, sizeof(i));
|
|
}
|
|
|
|
RegInProgress = FALSE;
|
|
|
|
if (Verbose) {
|
|
printf ("Registry path:\n%s\n", s);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
AddRun (
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
) {
|
|
PREGISTRY_HEADER regHdr;
|
|
ULONG RunLength;
|
|
|
|
|
|
do {
|
|
if (RegDataSize + sizeof(REGISTRY_HEADER) > DATA_SIZE - 128) {
|
|
FlushRun ();
|
|
}
|
|
|
|
regHdr = (PREGISTRY_HEADER) (RegDataBuffer + RegDataSize);
|
|
RegDataSize += sizeof(REGISTRY_HEADER);
|
|
|
|
if (DATA_SIZE - RegDataSize < Length) {
|
|
RunLength = DATA_SIZE - RegDataSize;
|
|
} else {
|
|
RunLength = Length;
|
|
}
|
|
|
|
//printf ("Add Hdr %x %x\n", Offset, RunLength);
|
|
|
|
regHdr->Offset = Offset;
|
|
regHdr->Length = RunLength;
|
|
RtlCopyMemory (RegDataBuffer + RegDataSize, Update.Image + Offset, RunLength);
|
|
|
|
RegDataSize += RunLength;
|
|
Offset += RunLength;
|
|
Length -= RunLength;
|
|
} while (Length);
|
|
}
|
|
|
|
|
|
VOID
|
|
FlushRun
|
|
(
|
|
VOID
|
|
) {
|
|
LONG Status;
|
|
UCHAR s[50];
|
|
|
|
if (RegDataSize) {
|
|
sprintf (s, "%08x", RegDataSequence);
|
|
RegDataSequence += 1;
|
|
|
|
if (Verbose) {
|
|
printf ("SetValue %s\n", s);
|
|
}
|
|
|
|
Status = RegSetValueEx (RegKey, s, 0L, REG_BINARY, RegDataBuffer, RegDataSize);
|
|
RegDataSize = 0;
|
|
if (Status != ERROR_SUCCESS) {
|
|
printf ("Error writting registry value %s\n", s);
|
|
Abort();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DeleteRegistryNode (
|
|
IN HKEY Handle
|
|
) {
|
|
UCHAR s[500];
|
|
ULONG i;
|
|
LONG Status;
|
|
HKEY SubKey;
|
|
ULONG Type;
|
|
ULONG DataSize;
|
|
|
|
#if 0
|
|
i = 0;
|
|
for (; ;) {
|
|
Status = RegEnumKey(Handle, i, s, sizeof(s));
|
|
i += 1;
|
|
if (Status == ERROR_NO_MORE_ITEMS) {
|
|
break;
|
|
}
|
|
|
|
Status = RegOpenKey(Handle, s, &SubKey);
|
|
if (Status == ERROR_SUCCESS) {
|
|
DeleteRegistryNode (SubKey);
|
|
RegCloseKey (SubKey);
|
|
|
|
if (Verbose) {
|
|
printf ("Delete key %s\n", s);
|
|
}
|
|
RegDeleteKey (Handle, s);
|
|
i = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
i = 0;
|
|
for (; ;) {
|
|
s[0] = 0;
|
|
DataSize = 0;
|
|
Status = RegEnumValue(
|
|
Handle,
|
|
i,
|
|
s,
|
|
&DataSize,
|
|
NULL,
|
|
&Type,
|
|
NULL,
|
|
0
|
|
);
|
|
i += 1;
|
|
if (Status == ERROR_NO_MORE_ITEMS) {
|
|
break;
|
|
}
|
|
|
|
s[DataSize] = 0;
|
|
if (Verbose) {
|
|
printf ("Delete value %s\n", s);
|
|
}
|
|
|
|
Status = RegDeleteValue (Handle, s);
|
|
if (Status == ERROR_SUCCESS) {
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
GetRegistryKey (
|
|
IN PIFILE Image
|
|
) {
|
|
LONG Status;
|
|
|
|
sprintf (s, "System\\CurrentControlSet\\Services\\ACPI\\Parameters\\%c%c%c%c\\%s\\%s\\%.8x",
|
|
signa[0],
|
|
signa[1],
|
|
signa[2],
|
|
signa[3],
|
|
Image->OemID,
|
|
Image->OemTableID,
|
|
Image->OemRevision
|
|
);
|
|
|
|
Status = RegCreateKey (HKEY_LOCAL_MACHINE, s, &RegKey);
|
|
if (Status == ERROR_SUCCESS) {
|
|
RegCloseKey (RegKey);
|
|
}
|
|
|
|
Status = RegOpenKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
s,
|
|
0L,
|
|
KEY_ALL_ACCESS,
|
|
&RegKey
|
|
);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
RegKey = NULL;
|
|
printf ("Count not access the registry path: %s\n", s);
|
|
Abort ();
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
CheckImageHeader (
|
|
IN PIFILE File
|
|
) {
|
|
PUCHAR Image;
|
|
PDSDT Dsdt; // Variable name kept as Dsdt even though this program can handle all types
|
|
UCHAR check;
|
|
ULONG i;
|
|
BOOL found = FALSE;
|
|
//ULONG signatures[] = SIGNATURES;
|
|
ULONG signatures[] = SIGNATURES;
|
|
|
|
|
|
if (File->FileSize < sizeof(DSDT)) {
|
|
FAbort ("Invalid image size in", File);
|
|
}
|
|
|
|
Dsdt = (PDSDT) File->Image;
|
|
|
|
for (i=0;i<sizeof(signatures);i++) {
|
|
if (signatures[i] == Dsdt->Signature) {
|
|
found = TRUE;
|
|
signa = (PUCHAR)(&(Dsdt->Signature));
|
|
break;
|
|
}
|
|
}
|
|
if (!found && !Force) {
|
|
UCHAR sig[64];
|
|
sprintf(sig, "Image signature (%c%c%c%c) not recognized in",
|
|
((PUCHAR)(&Dsdt->Signature))[0],
|
|
((PUCHAR)(&Dsdt->Signature))[1],
|
|
((PUCHAR)(&Dsdt->Signature))[2],
|
|
((PUCHAR)(&Dsdt->Signature))[3]);
|
|
FAbort (sig, File);
|
|
}
|
|
|
|
|
|
//
|
|
// BUGBUG: remove? (Or at least revision should be "1")
|
|
//
|
|
// if (Dsdt->Revision != 0) {
|
|
// FAbort ("DSDT revision not 0 in", File);
|
|
// }
|
|
|
|
if (File->FileSize != Dsdt->Length) {
|
|
UCHAR sig[64];
|
|
sprintf(sig, "File size in %c%c%c%c does not match image size in",
|
|
signa[0],
|
|
signa[1],
|
|
signa[2],
|
|
signa[3]);
|
|
FAbort (sig, File);
|
|
}
|
|
|
|
check = 0;
|
|
for (Image = File->Image; Image < File->EndOfImage; Image += 1) {
|
|
check += *Image;
|
|
}
|
|
|
|
if (check) {
|
|
FAbort ("Image checksum is incorrect in", File);
|
|
}
|
|
|
|
//
|
|
// normalize fixed strings
|
|
//
|
|
File->OemID = FixString (Dsdt->OemID, 6);
|
|
File->OemTableID = FixString (Dsdt->OemTableID, 8);
|
|
File->OemRevision = Dsdt->OemRevision;
|
|
|
|
|
|
// for (i=0; i < 4; i++) {
|
|
// if (File->OemRevision[i] == 0 || File->OemRevision[i] == ' ') {
|
|
// File->OemRevision[i] = '_';
|
|
// }
|
|
// }
|
|
|
|
if (Verbose) {
|
|
printf ("\n");
|
|
printf ("%c%c%c%c info for %s (%s)\n",
|
|
signa[0],
|
|
signa[1],
|
|
signa[2],
|
|
signa[3],
|
|
File->Desc, File->FileName);
|
|
printf (" Size of image: %d\n", File->FileSize);
|
|
printf (" OEM id.......: %s\n", File->OemID);
|
|
printf (" OEM Table id.: %s\n", File->OemTableID);
|
|
printf (" OEM revision.: %.8x\n", File->OemRevision);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PUCHAR
|
|
FixString (
|
|
IN PUCHAR Str,
|
|
IN ULONG Len
|
|
) {
|
|
PUCHAR p;
|
|
ULONG i;
|
|
|
|
p = malloc(Len+1);
|
|
memcpy (p, Str, Len);
|
|
p[Len] = 0;
|
|
|
|
for (i=Len; i; i--) {
|
|
if (p[i] != ' ') {
|
|
break;
|
|
}
|
|
p[i] = 0;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
VOID
|
|
FAbort (
|
|
PUCHAR Text,
|
|
PIFILE File
|
|
) {
|
|
|
|
printf ("%s %s (%s)\n", Text, File->Desc, File->FileName);
|
|
Abort();
|
|
}
|
|
|
|
|
|
VOID
|
|
Abort(
|
|
VOID
|
|
) {
|
|
if (RegInProgress) {
|
|
DeleteRegistryNode(RegKey);
|
|
}
|
|
|
|
if (!ArgsParsed) {
|
|
printf ("amlload: UpdateImage [OriginalImage] [-v] [-d] [-f]\n");
|
|
}
|
|
exit (1);
|
|
}
|
|
|
|
|
|
VOID
|
|
ParseArgs (
|
|
IN int argc,
|
|
IN char *argv[]
|
|
) {
|
|
PIFILE File;
|
|
OFSTRUCT OpenBuf;
|
|
|
|
File = &Update;
|
|
|
|
while (--argc) {
|
|
argv += 1;
|
|
|
|
//
|
|
// If it's a flag crack it
|
|
//
|
|
|
|
if (argv[0][0] == '-') {
|
|
switch (argv[0][1]) {
|
|
case 'v':
|
|
case 'V':
|
|
Verbose = TRUE;
|
|
break;
|
|
|
|
case 'd':
|
|
case 'D':
|
|
DeleteUpdate = TRUE;
|
|
break;
|
|
|
|
case 'f':
|
|
case 'F':
|
|
Force = TRUE;
|
|
break;
|
|
|
|
default:
|
|
printf ("Unknown flag %s\n", argv[0]);
|
|
Abort ();
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!File) {
|
|
printf ("Unexcepted parameter %s\n", argv[0]);
|
|
Abort();
|
|
}
|
|
|
|
//
|
|
// Open the file
|
|
//
|
|
|
|
File->FileName = argv[0];
|
|
File->FileHandle = (HANDLE) OpenFile(
|
|
argv[0],
|
|
&OpenBuf,
|
|
OF_READ
|
|
);
|
|
if (File->FileHandle == (HANDLE) HFILE_ERROR) {
|
|
FAbort ("Can not open", File);
|
|
}
|
|
|
|
File->FileSize = GetFileSize(File->FileHandle, NULL);
|
|
|
|
//
|
|
// Map it
|
|
//
|
|
|
|
File->MapHandle =
|
|
CreateFileMapping(
|
|
File->FileHandle,
|
|
NULL,
|
|
PAGE_READONLY,
|
|
0,
|
|
File->FileSize,
|
|
NULL
|
|
);
|
|
|
|
if (!File->MapHandle) {
|
|
FAbort ("Cannot map", File);
|
|
}
|
|
|
|
File->Image =
|
|
MapViewOfFile (
|
|
File->MapHandle,
|
|
FILE_MAP_READ,
|
|
0,
|
|
0,
|
|
File->FileSize
|
|
);
|
|
|
|
if (!File->Image) {
|
|
FAbort ("Cannot map view of image", File);
|
|
}
|
|
File->EndOfImage = File->Image + File->FileSize;
|
|
File->Opened = TRUE;
|
|
|
|
//
|
|
// Next file param
|
|
//
|
|
|
|
if (File == &Update) {
|
|
File = &Orig;
|
|
} else {
|
|
File = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// At least a update image is needed
|
|
//
|
|
|
|
if (!Update.Opened) {
|
|
Abort ();
|
|
}
|
|
|
|
ArgsParsed = TRUE;
|
|
return ;
|
|
}
|