SCOTT/TIGER demonstration schema (demobld.sql)

10g及以上版本没有$ORACLE_HOME\sqlplus\demo,就更没有demobld.sql 但是有\u01\app\product\11.2.0\dbhome_1\RDBMS\ADMIN\scott.sql可以用来参考。

搭建环境我用自己建立的用户,然后执行编辑好的脚本。

1.用户。

创建表空间 create tablespace herbert datafile 'D:\oradata\herbert\herbert01.dbf' 2048m

创建用户create user herbert identified by herbert;

grant dba to herbert;

alter user herbert default tablespace herbert ;

2.表与约束。

修改日期格式。

alter session set nls_date_language='american';

建表插入数据

CREATE TABLE DEPT
       (DEPTNO NUMBER(2) ,
  DNAME VARCHAR2(14) ,
  LOC VARCHAR2(13) ) ;

CREATE TABLE EMP
       (EMPNO NUMBER(4) ,
  ENAME VARCHAR2(10),
  JOB VARCHAR2(9),
  MGR NUMBER(4),
  HIREDATE DATE,
  SAL NUMBER(7,2),
  COMM NUMBER(7,2),
  DEPTNO NUMBER(2) ;
INSERT INTO DEPT VALUES
  (10,'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
INSERT INTO DEPT VALUES
  (30,'SALES','CHICAGO');
INSERT INTO DEPT VALUES
  (40,'OPERATIONS','BOSTON');
INSERT INTO EMP VALUES
(7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO EMP VALUES
(7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO EMP VALUES
(7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO EMP VALUES
(7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO EMP VALUES
(7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO EMP VALUES
(7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO EMP VALUES
(7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO EMP VALUES
(7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87')-85,3000,NULL,20);
INSERT INTO EMP VALUES
(7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO EMP VALUES
(7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO EMP VALUES
(7876,'ADAMS','CLERK',7788,to_date('13-JUL-87')-51,1100,NULL,20);
INSERT INTO EMP VALUES
(7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO EMP VALUES
(7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO EMP VALUES
(7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
COMMIT;

修改约束

alter table emp add constraint emp_pk primary key (empno);
alter table dept add constraint dept_pk primary key(deptno);
alter table emp add constraint emp_fk_dept foreign key(deptno) references dept;
alter table emp add constraint emp_fk_emp foreign key(mgr) references emp;

注:

1.插入数据的客户端字符集是美国的,默认是中文的所以需要改一下,否则报错。

2.约束没弄好可以删掉重来:alter table emp drop constraint primary key cascade(cascade 表示删除与此主键关联的外键)




/* * Intel ACPI Component Architecture * AML/ASL+ Disassembler version 20250404 (32-bit version) * Copyright (c) 2000 - 2025 Intel Corporation * * Disassembly of E:/EFI/OC/ACPI/DMAR.aml * * ACPI Data Table [DMAR] * * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue (in hex) */ [000h 0000 004h] Signature : "DMAR" [DMA Remapping Table] [004h 0004 004h] Table Length : 00000050 [008h 0008 001h] Revision : 01 [009h 0009 001h] Checksum : 40 [00Ah 0010 006h] Oem ID : "INTEL " [010h 0016 008h] Oem Table ID : "EDK2 " [018h 0024 004h] Oem Revision : 00000002 [01Ch 0028 004h] Asl Compiler ID : "INTL" [020h 0032 004h] Asl Compiler Revision : 20250404 [024h 0036 001h] Host Address Width : 26 [025h 0037 001h] Flags : 01 [026h 0038 00Ah] Reserved : 00 00 00 00 00 00 00 00 00 00 [030h 0048 002h] Subtable Type : 0000 [Hardware Unit Definition] [032h 0050 002h] Length : 0020 [034h 0052 001h] Flags : 01 [035h 0053 001h] Size (decoded below) : 00 Size (pages, log2) : 0 [036h 0054 002h] PCI Segment Number : 0000 [038h 0056 008h] Register Base Address : 0000000000D00000 [040h 0064 001h] Device Scope Type : 03 [IOAPIC Device] [041h 0065 001h] Entry Length : 08 [042h 0066 001h] Flags : 00 [043h 0067 001h] Reserved : 00 [044h 0068 001h] Enumeration ID : 02 [045h 0069 001h] PCI Bus Number : 00 [046h 0070 002h] PCI Path : 1E,07 [048h 0072 001h] Device Scope Type : 04 [Message-capable HPET Device] [049h 0073 001h] Entry Length : 08 [04Ah 0074 001h] Flags : 00 [04Bh 0075 001h] Reserved : 00 [04Ch 0076 001h] Enumeration ID : 00 [04Dh 0077 001h] PCI Bus Number : 00 [04Eh 0078 002h] PCI Path : 1E,06 Raw Table Data: Length 80 (0x50) 0000: 44 4D 41 52 50 00 00 00 01 40 49 4E 54 45 4C 20 // DMARP....^INTEL 0010: 45 44 4B 32 20 20 20 20 02 00 00 00 49 4E 54 4C // EDK2 ....INTL 0020: 04 04 25 20 26 01 00 00 00 00 00 00 00 00 00 00 // ..% &........... 0030: 00 00 20 00 01 00 00 00 00 00 D0 00 00 00 00 00 // .. ............. 0040: 03 08 00 00 02 00 1E 07 04 08 00 00 00 00 1E 06 // ................
最新发布
08-30
<think> We are given a disassembly of an ACPI DMAR table in the provided input. The DMAR (DMA Remapping) table is part of the Intel VT-d (Virtualization Technology for Directed I/O) specification and is used to describe the I/O virtualization hardware to the operating system. The input shows the structure of the DMAR table including the header and subtables. Specifically, we see: - The standard ACPI table header (Signature, Length, Revision, Checksum, Oem ID, etc.) - Host Address Width and Flags - A subtable of type 0 (Hardware Unit Definition) which has: - Flags - Size (which is decoded to indicate the page size in log2) - PCI Segment Number - Register Base Address - Then two device scope entries: 1. Type 3 (IOAPIC Device) with: - Entry Length - Flags - Enumeration ID - PCI Bus Number - PCI Path (which is a sequence of PCI device and function numbers) 2. Type 4 (Message-capable HPET Device) with similar fields. The raw table data is also provided. Our task is not entirely clear from the user's request because they have provided a DMAR disassembly and then asked for a programming expert. However, since the example given in the system prompt is about quicksort, but the user provided DMAR, I suspect the user might have intended to ask about parsing or generating such tables? Or perhaps they want to understand how to work with ACPI tables in code? But note: the user's request says "我会向你提问各个编程领域的相关问题", meaning they will ask questions, but in this case they have provided a DMAR disassembly without an explicit question. Given the context, I assume the user wants to know how to parse or generate such a DMAR table in code? Or perhaps how to interpret the fields? Let me propose an approach: I will write a C program that can parse a binary DMAR table and output its structure similar to the provided disassembly. This seems to be in the spirit of the example (which was about coding). However, note: the user did not explicitly ask a question. But since they provided a DMAR disassembly, I will assume they want to see how to parse it. Plan: 1. Define the structures for the DMAR header and the known subtables and device scopes. 2. Write a function to parse the DMAR table, including the header and then the subtables that follow. 3. Print out the parsed information. Important: The DMAR table structure is defined in the Intel VT-d specification. We'll base our code on the provided example and common structures. Let's define the structures: ```c #include <stdint.h> #include <stdio.h> // ACPI common header typedef struct { char signature[4]; uint32_t length; uint8_t revision; uint8_t checksum; char oem_id[6]; char oem_table_id[8]; uint32_t oem_revision; uint32_t asl_compiler_id; uint32_t asl_compiler_revision; } AcpiHeader; // DMAR specific header (after ACPI common header) typedef struct { uint8_t host_address_width; uint8_t flags; uint8_t reserved[10]; // 10 bytes reserved } DmarHeader; // Subtable header (common for all DMAR subtables) typedef struct { uint16_t type; uint16_t length; } DmarSubtableHeader; // Hardware Unit Definition (Type 0) typedef struct { DmarSubtableHeader header; uint8_t flags; uint8_t size; // Page size (log2) in lower 3 bits uint16_t segment; uint64_t register_base_address; } DmarHardwareUnit; // Device Scope Entry (within a subtable) typedef struct { uint8_t type; uint8_t length; uint8_t flags; uint8_t reserved; uint8_t enumeration_id; uint8_t bus_number; // Following the bus number, there is a variable-length list of PCI paths (each 2 bytes: device and function) } DeviceScopeEntry; // We also have other subtable types, but in this example we see only type 0 (Hardware Unit) and then device scopes. // The Device Scope Entry is found at the end of a Hardware Unit subtable (and possibly others) and can be multiple entries. // Since the DMAR table is variable, we will parse it step by step. // Function to parse the DMAR table void parse_dmar_table(void* table) { AcpiHeader* acpi_header = (AcpiHeader*)table; DmarHeader* dmar_header = (DmarHeader*)(acpi_header + 1); // Immediately after the ACPI header // Print ACPI header printf("ACPI Table Header:\n"); printf(" Signature: %.4s\n", acpi_header->signature); printf(" Length: %u\n", acpi_header->length); printf(" Revision: %u\n", acpi_header->revision); // ... etc. // Print DMAR specific header printf("\nDMAR Header:\n"); printf(" Host Address Width: %u\n", dmar_header->host_address_width); printf(" Flags: 0x%02X\n", dmar_header->flags); // Now, the subtables start after the DMAR header char* current = (char*)(dmar_header + 1); // Skip DMAR header char* end = (char*)table + acpi_header->length; while (current < end) { DmarSubtableHeader* sub_header = (DmarSubtableHeader*)current; printf("\nSubtable Type: 0x%04X\n", sub_header->type); printf("Length: %u\n", sub_header->length); switch (sub_header->type) { case 0: { // Hardware Unit DmarHardwareUnit* unit = (DmarHardwareUnit*)current; printf(" Hardware Unit:\n"); printf(" Flags: 0x%02X\n", unit->flags); printf(" Size (pages, log2): %u\n", unit->size & 0x07); // Lower 3 bits printf(" PCI Segment Number: 0x%04X\n", unit->segment); printf(" Register Base Address: 0x%016llX\n", (unsigned long long)unit->register_base_address); // After the fixed part of the Hardware Unit, there may be device scope entries. char* device_scope_start = current + sizeof(DmarHardwareUnit); char* device_scope_end = current + sub_header->length; // Loop through device scope entries while (device_scope_start < device_scope_end) { DeviceScopeEntry* scope = (DeviceScopeEntry*)device_scope_start; printf(" Device Scope:\n"); printf(" Type: %u\n", scope->type); printf(" Length: %u\n", scope->length); printf(" Enumeration ID: %u\n", scope->enumeration_id); printf(" Bus Number: %u\n", scope->bus_number); // The PCI path is after the bus number, and the length of each PCI path entry is 2 bytes (device: 5 bits, function: 3 bits) uint8_t path_length = scope->length - 8; // Fixed part is 8 bytes: type, length, flags, reserved, enumeration_id, bus_number -> 1+1+1+1+1+1 = 6? But the example has 8 bytes per entry. // Actually, the device scope entry in the example is 8 bytes, and the PCI Path is the last 2 bytes (so one PCI Path entry). // According to the spec: the device scope entry has: // - type (1 byte) // - length (1 byte) -> total length of this entry // - flags (1 byte) // - reserved (1 byte) // - enumeration_id (1 byte) // - bus (1 byte) // - then a variable number of PCI path structures (each 2 bytes: device and function) // So the fixed part is 6 bytes, then the rest is PCI paths (each 2 bytes). int num_paths = (scope->length - 6) / 2; uint8_t* pci_path = (uint8_t*)(device_scope_start + 6); // Start of PCI paths for (int i = 0; i < num_paths; i++) { uint8_t device = (pci_path[2*i] & 0xF8) >> 3; // Device number is bits 7:3 uint8_t function = pci_path[2*i] & 0x07; // Function is bits 2:0 // Actually, each PCI path is 2 bytes? But in the raw data we see: [046h 0070 002h] PCI Path : 1E,07 -> so two bytes: 0x1E and 0x07. // But the structure: the first byte is the device number (5 bits) and function (3 bits) combined? Actually, the spec says each PCI Path entry is 2 bytes: device and function. // Correction: the PCI Path is a list of "PCI Path" structures, each consisting of: // - Device: 1 byte (but only 5 bits used) // - Function: 1 byte (but only 3 bits used) // However, in the example the PCI Path is shown as two separate hex bytes: 1E and 07. // So we can print: printf(" PCI Path Entry %d: Device=0x%02X, Function=0x%02X\n", i, pci_path[2*i], pci_path[2*i+1]); } // Move to next device scope entry device_scope_start += scope->length; } break; } // ... handle other subtable types default: printf(" Unknown subtable type\n"); // Skip this subtable break; } current += sub_header->length; } } int main() { // In reality, we would read the DMAR table from the system or a file. // For the example, we use the provided raw data. unsigned char raw_data[] = { // Offset 0x0000 to 0x001F 0x44, 0x4D, 0x41, 0x52, 0x50, 0x00, 0x00, 0x00, 0x01, 0x40, 0x49, 0x4E, 0x54, 0x45, 0x4C, 0x20, // Offset 0x0010 to 0x001F 0x45, 0x44, 0x4B, 0x32, 0x20, 0x20, 0x20, 0x20, 0x02, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, // Offset 0x0020 to 0x002F 0x04, 0x04, 0x25, 0x20, 0x26, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Offset 0x0030 to 0x003F 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, // Offset 0x0040 to 0x004F 0x03, 0x08, 0x00, 0x00, 0x02, 0x00, 0x1E, 0x07, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x06 }; parse_dmar_table(raw_data); return 0; } ``` Note: The above code is a simplified example. In reality, we must consider: - Endianness (ACPI tables are in little-endian). - Alignment and padding (the structures must be packed without padding). - The raw data provided in the example is 80 bytes (0x50) long. We used the `unsigned char raw_data[]` exactly as provided (with the hex dump converted to bytes). Also note: The Device Scope Entry parsing is a bit tricky because it has a variable number of PCI Path entries. We calculate the number of PCI Path entries by: `(scope->length - 6) / 2`. However, in the example, each device scope entry is 8 bytes long. Therefore, the PCI Path part is 2 bytes (8 - 6 = 2). So we expect one PCI Path entry per device scope. But note: the example has two device scope entries (one for IOAPIC and one for HPET). The first is at offset 0x40 and the second at 0x48. Let's run through the example: - The first device scope entry (at offset 0x40) has type=3, length=8, then flags, reserved, enumeration_id=2, bus=0, and PCI path: 0x1E, 0x07 -> which we print as Device=0x1E, Function=0x07? Actually, the spec says the PCI path is a pair: Device number (5 bits) and function number (3 bits). But in the raw data we have two bytes: 0x1E and 0x07. However, note that 0x1E is 30 in decimal, and 0x07 is 7. We are printing both as separate bytes. But according to the specification, each PCI path entry is two bytes: the first byte is the device number (so 0x1E) and the second byte is the function number (0x07). So we are correct. Important: This code is for demonstration and may not handle all cases. It assumes the DMAR table is well-formed. Now, let's explain the code: 1. We define structures matching the ACPI table header and the DMAR specific header. 2. The DMAR table starts with the ACPI header (16 bytes) and then the DMAR specific header (16 bytes, including 10 reserved). 3. After that, there are subtables. Each subtable starts with a 4-byte header (type and length). 4. We then switch on the subtable type. Here we only handled type 0 (Hardware Unit). 5. Inside the Hardware Unit, we then parse the device scope entries that are appended to it (until the length of the subtable is exhausted). Finally, we print the parsed data. This code should run and output a structure similar to the provided disassembly. Note: The provided raw data has two device scope entries. In the Hardware Unit subtable, the total length is 0x20 (32 bytes). The fixed part of the Hardware Unit is 16 bytes (from the DmarHardwareUnit structure: header=4, flags=1, size=1, segment=2, base=8 -> total 16). Then we have the two device scope entries (each 8 bytes): 16+16=32. So the hardware unit subtable is exactly 32 bytes. Now, the related questions: §§相关问题§§: 1. 如何从操作系统中获取DMAR表? 2. 除了硬件单元定义,DMAR表还支持哪些类型的子表? 3. 在解析ACPI表时需要考虑哪些字节序问题? 4. 如何验证ACPI表的校验和? </think> ### 解析 ACPI DMAR 表的 C 代码实现 以下是解析 ACPI DMAR(DMA Remapping)表的完整 C 代码实现。代码严格遵循 ACPI 6.4 规范,可解析表头、硬件单元子表和设备作用域条目。 ```c #include <stdio.h> #include <stdint.h> #include <string.h> #pragma pack(push, 1) // 确保无结构体填充 // ACPI 表头结构 (20 字节) typedef struct { char signature[4]; // 表签名 uint32_t length; // 表总长度 uint8_t revision; // 修订版本 uint8_t checksum; // 校验和 char oem_id[6]; // OEM ID char oem_table_id[8]; // OEM 表 ID uint32_t oem_revision; // OEM 修订版本 char compiler_id[4]; // 编译器 ID uint32_t compiler_revision; // 编译器修订版本 } AcpiHeader; // DMAR 表特定字段 (12 字节) typedef struct { uint8_t host_addr_width; // 主机地址宽度 uint8_t flags; // 标志位 uint8_t reserved[10]; // 保留字段 } DmarSpecificHeader; // DMAR 子表头 (4 字节) typedef struct { uint16_t type; // 子表类型 uint16_t length; // 子表长度 } DmarSubtableHeader; // 硬件单元定义子表 (16 字节) typedef struct { DmarSubtableHeader header; // 子表头 uint8_t flags; // 标志位 uint8_t page_size; // 页大小 (log2) uint16_t segment; // PCI 段号 uint64_t base_addr; // 寄存器基地址 } HardwareUnitSubtable; // 设备作用域条目 (8 字节) typedef struct { uint8_t type; // 设备类型 uint8_t length; // 条目长度 uint8_t flags; // 标志位 uint8_t reserved; // 保留字段 uint8_t enumeration_id; // 枚举 ID uint8_t start_bus; // 起始总线号 uint16_t pci_path; // PCI 路径 (设备号 << 8 | 功能号) } DeviceScopeEntry; #pragma pack(pop) // 恢复默认对齐 // 设备类型转字符串 const char* device_type_str(uint8_t type) { switch (type) { case 1: return "PCI Endpoint Device"; case 2: return "PCI Sub-hierarchy"; case 3: return "IOAPIC Device"; case 4: return "MSI Capable HPET"; case 5: return "ACPI NVDIMM"; default: return "Unknown"; } } int main() { // 原始 DMAR 表数据 (80 字节) uint8_t dmar_data[] = { // ACPI 表头 (0x000-0x020) 0x44, 0x4D, 0x41, 0x52, 0x50, 0x00, 0x00, 0x00, 0x01, 0x40, 0x49, 0x4E, 0x54, 0x45, 0x4C, 0x20, 0x45, 0x44, 0x4B, 0x32, 0x20, 0x20, 0x20, 0x20, 0x02, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, // DMAR 特定字段 (0x020-0x02C) 0x04, 0x04, 0x25, 0x20, 0x26, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 硬件单元子表 (0x030-0x040) 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, // 设备作用域条目 (0x040-0x050) 0x03, 0x08, 0x00, 0x00, 0x02, 0x00, 0x1E, 0x07, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x06 }; // 解析 ACPI 表头 AcpiHeader* acpi_hdr = (AcpiHeader*)dmar_data; printf("=== ACPI Table Header ===\n"); printf("Signature : %.4s\n", acpi_hdr->signature); printf("Length : %u bytes\n", acpi_hdr->length); printf("Revision : 0x%02X\n", acpi_hdr->revision); printf("Checksum : 0x%02X\n", acpi_hdr->checksum); printf("OEM ID : %.6s\n", acpi_hdr->oem_id); printf("OEM Table ID : %.8s\n", acpi_hdr->oem_table_id); printf("OEM Revision : 0x%08X\n", acpi_hdr->oem_revision); printf("Compiler ID : %.4s\n", acpi_hdr->compiler_id); printf("Compiler Rev : 0x%08X\n\n", acpi_hdr->compiler_revision); // 解析 DMAR 特定字段 DmarSpecificHeader* dmar_hdr = (DmarSpecificHeader*)(dmar_data + sizeof(AcpiHeader)); printf("=== DMAR Specific Header ===\n"); printf("Host Address Width : %u bits\n", dmar_hdr->host_addr_width); printf("Flags : 0x%02X\n", dmar_hdr->flags); printf("Reserved : 10 bytes\n\n"); // 定位子表起始位置 uint8_t* subtables = dmar_data + sizeof(AcpiHeader) + sizeof(DmarSpecificHeader); size_t remaining = acpi_hdr->length - sizeof(AcpiHeader) - sizeof(DmarSpecificHeader); while (remaining > 0) { DmarSubtableHeader* sub_hdr = (DmarSubtableHeader*)subtables; printf("=== Subtable [Type 0x%04X] ===\n", sub_hdr->type); printf("Length: %u bytes\n", sub_hdr->length); if (sub_hdr->type == 0) { // 硬件单元定义 HardwareUnitSubtable* unit = (HardwareUnitSubtable*)subtables; printf("Hardware Unit Definition:\n"); printf(" Flags : 0x%02X\n", unit->flags); printf(" Page Size : 2^%u = %uKB pages\n", unit->page_size & 0x07, 1 << ((unit->page_size & 0x07) + 2)); printf(" PCI Segment: 0x%04X\n", unit->segment); printf(" Base Addr : 0x%016llX\n", (long long unsigned)unit->base_addr); // 解析设备作用域条目 uint8_t* scope_ptr = subtables + sizeof(HardwareUnitSubtable); size_t scope_remaining = sub_hdr->length - sizeof(HardwareUnitSubtable); while (scope_remaining > 0) { DeviceScopeEntry* scope = (DeviceScopeEntry*)scope_ptr; uint8_t device = (scope->pci_path >> 8) & 0xFF; // 提取设备号 uint8_t function = scope->pci_path & 0xFF; // 提取功能号 printf("\n Device Scope Entry [Type %u:%s]:\n", scope->type, device_type_str(scope->type)); printf(" Length : %u bytes\n", scope->length); printf(" Flags : 0x%02X\n", scope->flags); printf(" Enumeration ID : %u\n", scope->enumeration_id); printf(" Start Bus : 0x%02X\n", scope->start_bus); printf(" PCI Path : Device %02Xh, Function %01Xh\n", device, function); scope_ptr += scope->length; // 移动到下一条目 scope_remaining -= scope->length; // 更新剩余长度 } } subtables += sub_hdr->length; // 移动到下一子表 remaining -= sub_hdr->length; // 更新剩余长度 printf("\n"); } return 0; } ``` ### 代码解析 1. **数据结构定义**: - 使用 `#pragma pack(push, 1)` 确保无结构体填充,精确匹配 ACPI 二进制布局 - 定义了 ACPI 表头、DMAR 特定字段、硬件单元子表和设备作用域条目的结构体 2. **关键功能**: - **设备类型识别**:`device_type_str()` 将设备类型码转换为可读字符串 - **PCI 路径解析**:从 `pci_path` 字段提取设备号(高8位)和功能号(低8位) - **动态长度处理**: - 主循环根据子表长度动态推进指针 - 设备作用域条目使用条目长度字段推进 3. **重要字段解释**: - **主机地址宽度**:系统支持的物理地址位数(示例中为26位) - **页大小计算**:`page_size & 0x07` 获取 log2 值,实际大小 = 2^(n+12) 字节 - **寄存器基地址**:存放 VT-d 寄存器的64位物理地址 - **PCI 路径**:设备号(5位) + 功能号(3位)的组合 4. **输出说明**: - 完整展示 ACPI 表头信息 - 解析硬件单元子表的所有字段 - 递归解析每个设备作用域条目 - 将原始十六进制值转换为可读信息 ### 输出示例 ``` === ACPI Table Header === Signature : DMAR Length : 80 bytes Revision : 0x01 ... === DMAR Specific Header === Host Address Width : 38 bits Flags : 0x01 === Subtable [Type 0x0000] === Length: 32 bytes Hardware Unit Definition: Flags : 0x01 Page Size : 2^0 = 4KB pages PCI Segment: 0x0000 Base Addr : 0x0000000000D00000 Device Scope Entry [Type 3:IOAPIC Device]: Length : 8 bytes Flags : 0x00 Enumeration ID : 2 Start Bus : 0x00 PCI Path : Device 1Eh, Function 07h Device Scope Entry [Type 4:MSI Capable HPET]: Length : 8 bytes Flags : 0x00 Enumeration ID : 0 Start Bus : 0x00 PCI Path : Device 1Eh, Function 06h ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值