Task 026: .AML File Format
Task 026: .AML File Format
1. List of Properties Intrinsic to the .AML File Format
The .AML file format, as defined in the ACPI specification, is a binary format for ACPI Machine Language (AML) bytecode, typically embedded within ACPI tables like DSDT or SSDT. The format begins with a fixed 36-byte header, followed by the AML bytecode. The intrinsic properties (structural elements) are:
- Table Signature: 4-byte ASCII string (e.g., "DSDT" or "SSDT"), identifying the table type.
- Table Length: 4-byte unsigned integer (little-endian), representing the total length of the file in bytes (including the header).
- Revision: 1-byte unsigned integer, indicating the ACPI specification revision the table complies with.
- Checksum: 1-byte unsigned integer, a byte-wise checksum of the entire file (must sum to 0 modulo 256 for validity).
- OEM ID: 6-byte ASCII string (null-padded if shorter), identifying the Original Equipment Manufacturer.
- OEM Table ID: 8-byte ASCII string (null-padded if shorter), providing an OEM-specific table identifier.
- OEM Revision: 4-byte unsigned integer (little-endian), the revision number assigned by the OEM.
- Creator ID: 4-byte ASCII string, identifying the vendor of the ASL compiler (e.g., "INTL" for Intel).
- Creator Revision: 4-byte unsigned integer (little-endian), the revision of the ASL compiler used to generate the file.
These properties are fixed in position and format, with all multi-byte integers in little-endian order. The remaining bytes after offset 36 contain the AML bytecode, which is not part of the header properties but defines the namespace objects and methods.
2. Two Direct Download Links for .AML Files
- https://raw.githubusercontent.com/dortania/Getting-Started-With-ACPI/master/extra-files/compiled/SSDT-CPUR.aml
- https://raw.githubusercontent.com/dortania/Getting-Started-With-ACPI/master/extra-files/compiled/SSDT-EC-DESKTOP.aml
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .AML File Dump
Drag and drop a .AML file here to dump its properties
4. Python Class for .AML File Handling
import struct
class AMLParser:
def __init__(self, filename=None):
self.signature = None
self.length = None
self.revision = None
self.checksum = None
self.oem_id = None
self.oem_table_id = None
self.oem_revision = None
self.creator_id = None
self.creator_revision = None
self.body = b'' # AML bytecode after header
if filename:
self.read(filename)
def read(self, filename):
with open(filename, 'rb') as f:
data = f.read()
if len(data) < 36:
raise ValueError("File too small to be a valid .AML")
(
self.signature,
self.length,
self.revision,
self.checksum,
self.oem_id,
self.oem_table_id,
self.oem_revision,
self.creator_id,
self.oem_revision
) = struct.unpack('<4s I B B 6s 8s I 4s I', data[:36])
self.signature = self.signature.decode('ascii')
self.oem_id = self.oem_id.decode('ascii').rstrip('\x00')
self.oem_table_id = self.oem_table_id.decode('ascii').rstrip('\x00')
self.creator_id = self.creator_id.decode('ascii')
self.body = data[36:]
# Validate length and checksum for completeness
if self.length != len(data):
print("Warning: Length mismatch")
computed_checksum = -sum(data) & 0xFF
if computed_checksum != 0:
print("Warning: Checksum invalid")
def print_properties(self):
if not self.signature:
raise ValueError("No file loaded")
print(f"Table Signature: {self.signature}")
print(f"Table Length: {self.length}")
print(f"Revision: {self.revision}")
print(f"Checksum: {self.checksum}")
print(f"OEM ID: {self.oem_id}")
print(f"OEM Table ID: {self.oem_table_id}")
print(f"OEM Revision: {self.oem_revision}")
print(f"Creator ID: {self.creator_id}")
print(f"Creator Revision: {self.creator_revision}")
def write(self, filename):
if not self.signature:
raise ValueError("No data to write")
header = struct.pack(
'<4s I B B 6s 8s I 4s I',
self.signature.encode('ascii'),
self.length,
self.revision,
self.checksum,
self.oem_id.encode('ascii').ljust(6, b'\x00'),
self.oem_table_id.encode('ascii').ljust(8, b'\x00'),
self.oem_revision,
self.creator_id.encode('ascii'),
self.creator_revision
)
data = header + self.body
# Update length and checksum if needed
self.length = len(data)
checksum = -sum(data) & 0xFF
data = data[:9] + struct.pack('B', checksum) + data[10:]
self.checksum = checksum
with open(filename, 'wb') as f:
f.write(data)
# Example usage:
# parser = AMLParser('example.aml')
# parser.print_properties()
# parser.write('output.aml')
5. Java Class for .AML File Handling
import java.io.*;
import java.nio.*;
import java.nio.file.*;
public class AMLParser {
private String signature;
private int length;
private byte revision;
private byte checksum;
private String oemId;
private String oemTableId;
private int oemRevision;
private String creatorId;
private int creatorRevision;
private byte[] body; // AML bytecode after header
public AMLParser(String filename) throws IOException {
read(filename);
}
public void read(String filename) throws IOException {
byte[] data = Files.readAllBytes(Paths.get(filename));
if (data.length < 36) {
throw new IllegalArgumentException("File too small to be a valid .AML");
}
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
byte[] sigBytes = new byte[4];
bb.get(sigBytes);
signature = new String(sigBytes);
length = bb.getInt();
revision = bb.get();
checksum = bb.get();
byte[] oemBytes = new byte[6];
bb.get(oemBytes);
oemId = new String(oemBytes).replaceAll("\0", "");
byte[] oemTblBytes = new byte[8];
bb.get(oemTblBytes);
oemTableId = new String(oemTblBytes).replaceAll("\0", "");
oemRevision = bb.getInt();
byte[] creBytes = new byte[4];
bb.get(creBytes);
creatorId = new String(creBytes);
creatorRevision = bb.getInt();
body = new byte[data.length - 36];
System.arraycopy(data, 36, body, 0, body.length);
// Validate length and checksum
if (length != data.length) {
System.out.println("Warning: Length mismatch");
}
int computedChecksum = 0;
for (byte b : data) {
computedChecksum = (computedChecksum + (b & 0xFF)) & 0xFF;
}
if (computedChecksum != 0) {
System.out.println("Warning: Checksum invalid");
}
}
public void printProperties() {
System.out.println("Table Signature: " + signature);
System.out.println("Table Length: " + length);
System.out.println("Revision: " + (revision & 0xFF));
System.out.println("Checksum: " + (checksum & 0xFF));
System.out.println("OEM ID: " + oemId);
System.out.println("OEM Table ID: " + oemTableId);
System.out.println("OEM Revision: " + oemRevision);
System.out.println("Creator ID: " + creatorId);
System.out.println("Creator Revision: " + creatorRevision);
}
public void write(String filename) throws IOException {
ByteBuffer bb = ByteBuffer.allocate(36 + body.length).order(ByteOrder.LITTLE_ENDIAN);
bb.put(signature.getBytes());
bb.putInt(length);
bb.put(revision);
bb.put(checksum);
bb.put(oemId.getBytes());
for (int i = oemId.length(); i < 6; i++) bb.put((byte) 0);
bb.put(oemTableId.getBytes());
for (int i = oemTableId.length(); i < 8; i++) bb.put((byte) 0);
bb.putInt(oemRevision);
bb.put(creatorId.getBytes());
bb.putInt(creatorRevision);
bb.put(body);
byte[] data = bb.array();
// Update length and checksum
length = data.length;
int sum = 0;
for (byte b : data) {
sum += b & 0xFF;
}
checksum = (byte) (-sum & 0xFF);
data[9] = checksum;
Files.write(Paths.get(filename), data);
}
// Example usage:
// public static void main(String[] args) throws IOException {
// AMLParser parser = new AMLParser("example.aml");
// parser.printProperties();
// parser.write("output.aml");
// }
}
6. JavaScript Class for .AML File Handling (Node.js)
const fs = require('fs');
class AMLParser {
constructor(filename = null) {
this.signature = null;
this.length = null;
this.revision = null;
this.checksum = null;
this.oemId = null;
this.oemTableId = null;
this.oemRevision = null;
this.creatorId = null;
this.creatorRevision = null;
this.body = Buffer.alloc(0); // AML bytecode after header
if (filename) {
this.read(filename);
}
}
read(filename) {
const data = fs.readFileSync(filename);
if (data.length < 36) {
throw new Error('File too small to be a valid .AML');
}
this.signature = data.slice(0, 4).toString('ascii');
this.length = data.readUInt32LE(4);
this.revision = data[8];
this.checksum = data[9];
this.oemId = data.slice(10, 16).toString('ascii').replace(/\0/g, '');
this.oemTableId = data.slice(16, 24).toString('ascii').replace(/\0/g, '');
this.oemRevision = data.readUInt32LE(24);
this.creatorId = data.slice(28, 32).toString('ascii');
this.creatorRevision = data.readUInt32LE(32);
this.body = data.slice(36);
// Validate length and checksum
if (this.length !== data.length) {
console.warn('Warning: Length mismatch');
}
let sum = 0;
for (let b of data) {
sum = (sum + (b & 0xFF)) & 0xFF;
}
if (sum !== 0) {
console.warn('Warning: Checksum invalid');
}
}
printProperties() {
console.log(`Table Signature: ${this.signature}`);
console.log(`Table Length: ${this.length}`);
console.log(`Revision: ${this.revision}`);
console.log(`Checksum: ${this.checksum}`);
console.log(`OEM ID: ${this.oemId}`);
console.log(`OEM Table ID: ${this.oemTableId}`);
console.log(`OEM Revision: ${this.oemRevision}`);
console.log(`Creator ID: ${this.creatorId}`);
console.log(`Creator Revision: ${this.creatorRevision}`);
}
write(filename) {
const header = Buffer.alloc(36);
header.write(this.signature, 0, 4, 'ascii');
header.writeUInt32LE(this.length, 4);
header[8] = this.revision;
header[9] = this.checksum;
header.write(this.oemId.padEnd(6, '\x00'), 10, 6, 'ascii');
header.write(this.oemTableId.padEnd(8, '\x00'), 16, 8, 'ascii');
header.writeUInt32LE(this.oemRevision, 24);
header.write(this.creatorId, 28, 4, 'ascii');
header.writeUInt32LE(this.creatorRevision, 32);
const data = Buffer.concat([header, this.body]);
// Update length and checksum
this.length = data.length;
let sum = 0;
for (let b of data) {
sum += b & 0xFF;
}
this.checksum = (-sum & 0xFF);
data[9] = this.checksum;
fs.writeFileSync(filename, data);
}
}
// Example usage:
// const parser = new AMLParser('example.aml');
// parser.printProperties();
// parser.write('output.aml');
7. C Class for .AML File Handling (Using C++ for Class Structure)
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdint>
#include <cstring>
class AMLParser {
private:
std::string signature;
uint32_t length;
uint8_t revision;
uint8_t checksum;
std::string oemId;
std::string oemTableId;
uint32_t oemRevision;
std::string creatorId;
uint32_t creatorRevision;
std::vector<uint8_t> body; // AML bytecode after header
public:
AMLParser(const std::string& filename = "") {
if (!filename.empty()) {
read(filename);
}
}
void read(const std::string& filename) {
std::ifstream file(filename, std::ios::binary | std::ios::ate);
if (!file) {
throw std::runtime_error("Unable to open file");
}
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> data(size);
if (!file.read(reinterpret_cast<char*>(data.data()), size)) {
throw std::runtime_error("Error reading file");
}
if (data.size() < 36) {
throw std::runtime_error("File too small to be a valid .AML");
}
signature.assign(reinterpret_cast<char*>(data.data()), 4);
memcpy(&length, data.data() + 4, 4);
revision = data[8];
checksum = data[9];
oemId.assign(reinterpret_cast<char*>(data.data() + 10), 6);
oemId.erase(oemId.find('\0'));
oemTableId.assign(reinterpret_cast<char*>(data.data() + 16), 8);
oemTableId.erase(oemTableId.find('\0'));
memcpy(&oemRevision, data.data() + 24, 4);
creatorId.assign(reinterpret_cast<char*>(data.data() + 28), 4);
memcpy(&creatorRevision, data.data() + 32, 4);
body.assign(data.begin() + 36, data.end());
// Validate length and checksum (little-endian assumed)
if (length != data.size()) {
std::cout << "Warning: Length mismatch" << std::endl;
}
uint8_t computedChecksum = 0;
for (uint8_t b : data) {
computedChecksum += b;
}
if (computedChecksum != 0) {
std::cout << "Warning: Checksum invalid" << std::endl;
}
}
void printProperties() const {
std::cout << "Table Signature: " << signature << std::endl;
std::cout << "Table Length: " << length << std::endl;
std::cout << "Revision: " << static_cast<unsigned>(revision) << std::endl;
std::cout << "Checksum: " << static_cast<unsigned>(checksum) << std::endl;
std::cout << "OEM ID: " << oemId << std::endl;
std::cout << "OEM Table ID: " << oemTableId << std::endl;
std::cout << "OEM Revision: " << oemRevision << std::endl;
std::cout << "Creator ID: " << creatorId << std::endl;
std::cout << "Creator Revision: " << creatorRevision << std::endl;
}
void write(const std::string& filename) const {
std::vector<uint8_t> data(36 + body.size());
memcpy(data.data(), signature.c_str(), 4);
memcpy(data.data() + 4, &length, 4);
data[8] = revision;
data[9] = checksum;
std::string paddedOem = oemId + std::string(6 - oemId.size(), '\0');
memcpy(data.data() + 10, paddedOem.c_str(), 6);
std::string paddedOemTbl = oemTableId + std::string(8 - oemTableId.size(), '\0');
memcpy(data.data() + 16, paddedOemTbl.c_str(), 8);
memcpy(data.data() + 24, &oemRevision, 4);
memcpy(data.data() + 28, creatorId.c_str(), 4);
memcpy(data.data() + 32, &creatorRevision, 4);
std::copy(body.begin(), body.end(), data.begin() + 36);
// Update length and checksum
uint32_t newLength = static_cast<uint32_t>(data.size());
memcpy(data.data() + 4, &newLength, 4);
uint8_t newChecksum = 0;
for (uint8_t b : data) {
newChecksum += b;
}
newChecksum = -newChecksum;
data[9] = newChecksum;
std::ofstream file(filename, std::ios::binary);
if (!file.write(reinterpret_cast<const char*>(data.data()), data.size())) {
throw std::runtime_error("Error writing file");
}
}
};
// Example usage:
// int main() {
// try {
// AMLParser parser("example.aml");
// parser.printProperties();
// parser.write("output.aml");
// } catch (const std::exception& e) {
// std::cerr << e.what() << std::endl;
// }
// return 0;
// }