/*++ 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 #include #include #include //#include #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;iSignature) { 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 ; }