windows-nt/Source/XPSP1/NT/base/busdrv/acpi/tools/acpiload/acpiload.c

704 lines
14 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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 ;
}