Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: IPMI SSIF Multi-part Read Middle incorrectly expects Block Number to start at 1 #188

Closed
1 task done
jls5177 opened this issue Dec 5, 2023 · 0 comments · Fixed by #189
Closed
1 task done
Labels
state:needs-maintainer-feedback Needs more information from a maintainer to determine next steps state:needs-triage Needs to triaged to determine next steps type:bug Something isn't working urgency:high Significant with a critical impact

Comments

@jls5177
Copy link

jls5177 commented Dec 5, 2023

Is there an existing issue for this?

  • I have searched existing issues

Current Behavior

According to the SSIF spec, the BMC Multi-part Read Middle should start with block number equal to 0.

image

However, the current code is expecting the first "middle" response to have a block number that starts at 1: https://github.com/microsoft/mu_feature_ipmi/blob/main/IpmiFeaturePkg/Library/IpmiTransportLibSsif/Ssif.c#L189C1-L196C8

// set when parsing the Multi-part "start" response
BlockNumber     = 0;

// executed when the "middle" response is received
if (BlockBuffer[0] != BlockNumber + 1) {
   // out-of-sequence error
}

BlockNumber = BlockBuffer[0];

This issue is not observed in Windows/Linux IPMI SSIF interfaces. We can review the Linux kernel SSIF driver to compare the behavior: https://github.com/torvalds/linux/blob/master/drivers/char/ipmi/ipmi_ssif.c#L710C1-L721C4

// set when parsing the Multi-part "start" response
ssif_info->multi_pos = 1;

// executed when the "middle" response is received
blocknum = data[0];
// ...
if (blocknum == 0xff) {
  // handle last "middle" packet
} else if (blocknum + 1 != ssif_info->multi_pos) {
   // out-of-sequence error
}

We can see the Linux kernel SSIF driver is setting the expected block number (blocknum) to 1 as it uses this to track outstanding multi-part reads. But then it compares the received block number (blocknum) to the expected blocknum but it increments by 1 to account for multi_pos not starting at 0.

Expected Behavior

The expectation is for the driver to align to the SSIF spec. This behavior ensures the same BMC firmware can work across all server environments (Windows, Linux, UEIF, BSD, ...).

Steps To Reproduce

  1. Run IPMI SSIF request that generates a multi-part read from the BMC with a size of at least 33 bytes (e.g., reading the FRU).
  2. If the BMC follows the spec: this will fail
  3. If the BMC modified their code to support this UEFI specific behavior: this will succeed, but performing the same SSIF multi-part read from within Linux will fail.

Build Environment

- OS(s):
- Tool Chain(s):
- Targets Impacted:

Version Information

This issue is present in the default branch. I am unsure how far back this change goes.

Urgency

High

Are you going to fix this?

I will fix it

Do you need maintainer feedback?

Maintainer feedback requested

Anything else?

I've captured a Linux kernel trace log from a system with a BMC that aligns to this broken UEFI behavior which causes the Linux IPMI SSIF command to fail:

       kssif0010-1278    [002] ..... 268046.323474: smbus_read: i2c-0 a=010 f=0000 c=3 BLOCK_DATA
       kssif0010-1278    [002] ..... 268046.323478: i2c_write: i2c-0 #0 a=010 f=0000 l=1 [03]
       kssif0010-1278    [002] ..... 268046.323479: i2c_read: i2c-0 #1 a=010 f=0601 l=1
       kssif0010-1278    [002] ..... 268046.324301: i2c_reply: i2c-0 #1 a=010 f=0201 l=33 [20-00-01-**redacted**]
       kssif0010-1278    [002] ..... 268046.324303: i2c_result: i2c-0 n=2 ret=2
       kssif0010-1278    [002] ..... 268046.324306: smbus_reply: i2c-0 a=010 f=0000 c=3 BLOCK_DATA l=33 [20-00-01-**redacted**]
       kssif0010-1278    [002] ..... 268046.324307: smbus_result: i2c-0 a=010 f=0000 c=3 BLOCK_DATA rd res=0
       kssif0010-1278    [002] ..... 268046.324312: smbus_read: i2c-0 a=010 f=0000 c=9 BLOCK_DATA
       kssif0010-1278    [002] ..... 268046.324315: i2c_write: i2c-0 #0 a=010 f=0000 l=1 [09]
       kssif0010-1278    [002] ..... 268046.324316: i2c_read: i2c-0 #1 a=010 f=0601 l=1
       kssif0010-1278    [002] ..... 268046.325133: i2c_reply: i2c-0 #1 a=010 f=0201 l=33 [20-01-**redacted**]
       kssif0010-1278    [002] ..... 268046.325135: i2c_result: i2c-0 n=2 ret=2
       kssif0010-1278    [002] ..... 268046.325138: smbus_reply: i2c-0 a=010 f=0000 c=9 BLOCK_DATA l=33 [20-01-**redacted**]
       kssif0010-1278    [002] ..... 268046.325139: smbus_result: i2c-0 a=010 f=0000 c=9 BLOCK_DATA rd res=0

The observed behavior within Linux is the IPMI SSIF driver receives the "start" packet and a single "middle" packet then it fails with an "out-of-sequence" error message.

@jls5177 jls5177 added state:needs-triage Needs to triaged to determine next steps type:bug Something isn't working labels Dec 5, 2023
@github-actions github-actions bot added state:needs-maintainer-feedback Needs more information from a maintainer to determine next steps urgency:high Significant with a critical impact labels Dec 5, 2023
pharlikar added a commit to pharlikar/mu_feature_ipmi that referenced this issue Dec 5, 2023
this is to fix multi-part read issue explained in this bug microsoft#188
@apop5 apop5 linked a pull request Dec 5, 2023 that will close this issue
5 tasks
@apop5 apop5 closed this as completed in #189 Dec 5, 2023
apop5 pushed a commit that referenced this issue Dec 5, 2023
## Description

this is to fix multi-part read issue explained in this bug
#188

- [x] Impacts functionality?
- **Functionality** - Does the change ultimately impact how firmware
functions?
- Examples: Add a new library, publish a new PPI, update an algorithm,
...
- [ ] Impacts security?
- **Security** - Does the change have a direct security impact on an
application,
    flow, or firmware?
  - Examples: Crypto algorithm change, buffer overflow fix, parameter
    validation improvement, ...
- [ ] Breaking change?
- **Breaking change** - Will anyone consuming this change experience a
break
    in build or boot behavior?
- Examples: Add a new library class, move a module to a different repo,
call
    a function in a new library class in a pre-existing module, ...
- [ ] Includes tests?
  - **Tests** - Does the change include any explicit test code?
  - Examples: Unit tests, integration tests, robot tests, ...
- [ ] Includes documentation?
- **Documentation** - Does the change contain explicit documentation
additions
    outside direct code modifications (and comments)?
- Examples: Update readme file, add feature readme file, link to
documentation
    on an a separate Web page, ...

## How This Was Tested

The change was tested with latest BMC that is spec compliant. 

## Integration Instructions

<_Describe how these changes should be integrated. Use N/A if nothing is
required._>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state:needs-maintainer-feedback Needs more information from a maintainer to determine next steps state:needs-triage Needs to triaged to determine next steps type:bug Something isn't working urgency:high Significant with a critical impact
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant