Skip to content

LpcACPIEC: add atomic read and range IOCTLs - #88

Draft
FengXi7420 wants to merge 3 commits into
namazso:mainfrom
FengXi7420:codex/lpc-acpi-ec-batch-read
Draft

LpcACPIEC: add atomic read and range IOCTLs#88
FengXi7420 wants to merge 3 commits into
namazso:mainfrom
FengXi7420:codex/lpc-acpi-ec-batch-read

Conversation

@FengXi7420

Copy link
Copy Markdown
Contributor

Summary

  • move the complete standard ACPI EC RD_EC sequence into LpcACPIEC
  • add ioctl_ec_read_byte and one-request ioctl_ec_read_range
  • keep the existing raw port IOCTLs for compatibility
  • validate the register range and exact output cell count before touching the EC
  • buffer a range locally so a timeout never returns a partial snapshot as success

The caller must continue to hold \\BaseNamedObjects\\Access_EC for the complete request.

Scope

This is intentionally the read-only first stage of #7. It does not add a high-level write IOCTL and does not use the optional EC hardware Burst Mode (0x82/0x83). A range is still a sequence of standard RD_EC commands, but it executes inside one PawnIO request.

The module and caller-side contract have been compiled and statically validated. Runtime testing of the new module is still pending because the available production PawnIO installation rejects locally built unsigned modules.

Validation

  • compiled all 22 modules with Pawn 4.1.7152 and the repository CI flags
  • tests/lpc_acpi_ec_batch_contract.ps1
  • boundary coverage includes zero length, full 256-byte space, crossing 0xFF, and exact packed output sizing

@namazso
namazso marked this pull request as draft August 30, 2026 00:29
@namazso

namazso commented Aug 30, 2026

Copy link
Copy Markdown
Owner

I changed this to draft, please test it on the unrestricted driver (you'll have to use 2.1.0 or your own builds because 2.2.0 accidentally shipped with signature verification enabled on the unrestricted driver as well) before marking it as ready.

Also get rid of the "test" that checks substrings on the source code, wtf...

@FengXi7420

Copy link
Copy Markdown
Contributor Author

Thanks for the clarification. Understood:\n\n- We will keep the PR as Draft.\n- We will test the module with the unrestricted 2.1.0 driver or a locally built equivalent, and will not use 2.2.0 because of the signature-verification regression.\n- The source-substring test has been removed in commit 38d1017.\n\nWe have not marked the PR ready. We will report the actual runtime result here after testing with the unrestricted driver.

@FengXi7420

Copy link
Copy Markdown
Contributor Author

Runtime testing is complete. I kept the PR as Draft and did not mark it ready.

Test setup:

  • Windows x64
  • locally built x64 PAWNIO_UNRESTRICTED driver from the 2.1.0 source
  • PR HEAD 38d10175b5b0ece4fdfaf184554e24503f51363a
  • locally rebuilt LpcACPIEC module

Single-run results (21 cases total):

  • Module load: PASS.
  • Valid ioctl_ec_read_byte: 3/3 PASS.
  • Valid ioctl_ec_read_range: 1/4 PASS; the other 3 returned NTSTATUS 0xC00000B5 / Win32 error 121 (ERROR_SEM_TIMEOUT).
  • Invalid-input and boundary rejection cases: 14/14 PASS (STATUS_INVALID_PARAMETER / Win32 87 where applicable).
  • No write IOCTL, port-output call, or EC write entry was invoked.

Overall result: FAIL (client exit code 7). The module loads and byte reads work on this machine, but the full range-read contract does not pass because the valid range cases at the end of the EC address space timed out. I will leave the PR in Draft. The exact stdout/stderr and hashes are available if you need them.

@FengXi7420

Copy link
Copy Markdown
Contributor Author

I found and fixed a separate deterministic issue in the range-output path.

The previous range_00_01 result was:

00 6F 63 74 6C 5F 65 63

pack_bytes_le only writes the requested byte count. Because this IOCTL uses METHOD_BUFFERED, the unused bytes in the final output cell retained bytes from the shared input/output buffer (the function-name prefix). That is a module-side output-contract bug, independent of the EC timeout cases.

Commit 0850bdf clears all required output cells immediately before packing, after every EC read has succeeded. This makes unused bytes in a partial final cell deterministic zero and preserves the existing failure behavior.

Verification:

  • Pawn compiler 4.1.7152 with the CI flags (-iinclude -C64 -;+ -(+ -p): 0 errors, 0 warnings.
  • Offline source-order and partial-cell padding checks: pass.
  • No hardware retest was performed after the driver cleanup. The three prior STATUS_IO_TIMEOUT cases (0xFE/2, 0xFF/1, 0x00/256) remain explicitly unresolved and may be machine/EC-specific; they are not being claimed as fixed by this commit.

@FengXi7420

Copy link
Copy Markdown
Contributor Author

Runtime retest completed with the patched module from commit 0850bdf.

Setup:

  • Reused the already-loaded local unrestricted 2.1 test driver; no 2.2.0 installation.
  • Patched AMX: 9008 bytes, SHA-256 B469741E532B5CDFCA0662B471C045A74C316C9A05293ED56E435DE0DA107301.
  • Read-only client only; no write IOCTL, port-output call, or EC write.

Results:

  • Module load: PASS.
  • Invalid-input/boundary cases: 14/14 PASS.
  • Valid byte reads: 1/3 PASS in this run.
  • Valid range reads: 1/4 PASS.
  • range_00_01 now returns 0000000000000000; before the fix it returned 006F63746C5F6563. This confirms the partial-cell output padding fix through the real driver path.
  • The remaining failures returned STATUS_IO_TIMEOUT (0xC00000B5): byte_00, byte_42, range_fe_02, range_ff_01, and range_00_256.

The byte timeout set changed with the read order compared with the previous run, so I am treating these as an unresolved EC/protocol or machine-state issue rather than attributing them to the output-padding change. The temporary test service was stopped and deleted after the run. The PR remains Draft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants