{"id":18368766,"url":"https://github.com/openbmc/google-ipmi-i2c","last_synced_at":"2025-04-06T17:31:52.105Z","repository":{"id":74554680,"uuid":"154500541","full_name":"openbmc/google-ipmi-i2c","owner":"openbmc","description":"Google OEM IPMI Commands for I2C","archived":false,"fork":false,"pushed_at":"2025-03-18T20:50:06.000Z","size":66,"stargazers_count":10,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-18T21:35:19.011Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openbmc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-24T12:51:13.000Z","updated_at":"2025-03-18T20:50:10.000Z","dependencies_parsed_at":"2023-02-28T17:01:32.081Z","dependency_job_id":null,"html_url":"https://github.com/openbmc/google-ipmi-i2c","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openbmc%2Fgoogle-ipmi-i2c","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openbmc%2Fgoogle-ipmi-i2c/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openbmc%2Fgoogle-ipmi-i2c/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openbmc%2Fgoogle-ipmi-i2c/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openbmc","download_url":"https://codeload.github.com/openbmc/google-ipmi-i2c/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247522428,"owners_count":20952546,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T23:27:21.573Z","updated_at":"2025-04-06T17:31:52.094Z","avatar_url":"https://github.com/openbmc.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# I2C via IPMI Proxy Adapter\n\nAuthors: peterh@google.com\n\nLast Updated: 2017-05-16\n\n## Objective\n\nProvide a mechanism so that the host can manipulate I2C and SMBus devices on the\nassociated BMC.\n\n## Background\n\nRecent server systems come with a secondary processing system attached for the\npurpose of monitoring and control, generally referred to as a BMC. There is a\nlarge effort to develop an open source framework for writing applications and\ncontrol systems that will run on the BMC, known as OpenBMC. Within Google the\neffort has been internalized (while also providing upstream pushes) as gBMC. The\nprimary goal of OpenBMC is to support remote and local system management through\nseveral interfaces, IPMI being the one of interest here.\n\nHistorically, a host tool provides a kind of adaptation layer, enabling many\nsystem-level functions for Google Servers. Important functions presume direct\nI2C access, but with a BMC, the server is wired such that only the BMC has\ndirect access and control over many motherboard components, including\nsubstantially all I2C adapters. To resolve this inconsistency, OpenBMC will be\nextended to expose the needed I2C adapters for use by host tools.\n\nIPMI allows for OEM commands to provide custom information flow or system\ncontrol with a BMC. And OpenBmc now has its own IANA OEM Enterprise Number,\nwhich may be used when upstreaming such controls for general use.\n\n## Overview\n\nThe BMC IPMI daemon supports the addition of command handlers. So we will add an\nOEM Extension command for I2C transfer which will perform an I2C transfer and\nreturn the results.\n\nWith this piece, in theory a host tool's I2C I/O calls could be converted to the\nequivalent IPMI calls. However, in some cases, the host tool would be advised to\ninstantiate an I2C device and use a higher level API. As a simple example, we\nshould probably use the associated Linux driver, rather than raw I2C I/O, when\nreprogramming an at24c64d.\n\nSo we propose to create a proxy I2C adapter for each I2C bus we need to reach on\nthe BMD. This avoids the need to convert raw host I2C, and enables regular Linux\nI2C device drivers at the host to connect to actual devices on the BMC.\n\n## Detailed Design\n\n### IPMID OEM Command Extension Routing\n\n- Register wildcard command handler for any OEM Group Extension request (netfn\n  0x2e, cmd 0xff)\n- Provide for registration of OEN, command pairs\n- Route received requests to registered handler\n\n### IPMID Messages\n\n#### Request\n\n```\nNetFn    0x2e\nOemGroup 49871\nCmd      2 (openBmcI2cOemCmd)\n```\n\n##### Request Data\n\n| byte(s) | type     | ID       | Description                              |\n| ------- | -------- | -------- | ---------------------------------------- |\n| 0       | byte     | bus      | i2c adapater number at BMC               |\n| 1       | ReqFlags | reqFlags | Flags for request                        |\n|         |          |          | bit 7 - PEC flag for M_RECV_LEN transfer |\n|         |          |          | bits 6:0 - zero -reserved for future use |\n| 2+      | Step     | -        | One per struct i2c_msg in transfer.      |\n\n##### Each Request Step\n\n| byte(s) | type      | ID        | Description                                     |\n| ------- | --------- | --------- | ----------------------------------------------- |\n| 0       | byte      | devAndDir | bit 0: 1 if step is read, 0 if write            |\n|         |           |           | bits 7:1 i2c device address                     |\n| 1       | StepFlags | stepFlags | Flags fro each step                             |\n|         |           |           | bit 7: carries M_RECV_LEN bit - read steps only |\n|         |           |           | bit 6: reserved for M_NOSTART                   |\n| 2       | byte      | parm      | Transfer length (except M_RECV_LEN)             |\n| 3-p+2   | byte      | wr_data   | Write steps only: parm bytes of data to write.  |\n\n#### Response\n\n```\nNetFn    0x2e\nOemGroup 49871\nCmd      2 (openBmcI2cOemCmd)\ncc       Completion code\nData     Only if successful: all bytes read, in order received.\n```\n\n#### Message Example\n\n`i2c-1 0x50 FRU EEPROM`\n\n```\nContent, trailing zero bytes omitted.\n# i2cdump -f -y 1 0x50 b\n     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef\n00: 01 00 00 01 00 00 00 fe 01 0b 19 83 6a 99 c6 51    ?..?...?????j??Q\n10: 75 61 6e 74 61 d7 4d 65 6d 6f 72 79 20 52 69 73    uanta?Memory Ris\n20: 65 72 20 44 44 52 34 20 42 6f 61 72 64 cf 51 54    er DDR4 Board?QT\n30: 46 34 4b 31 31 35 30 37 30 30 32 33 38 cb 33 37    F4K1150700238?37\n40: 53 34 4c 52 42 30 30 32 30 c9 46 52 55 20 76 30    S4LRB0020?FRU v0\n50: 2e 30 31 c3 41 33 47 01 04 c1 00 00 00 00 00 99    .01?A3G???.....?\n\nRead `Quanta' from FRU at bus=1/addr=0x50/offset=15 at BMC.\n# ipmitool -I dbus raw 0x2e 2 0x79 0x2b 0x00 1 0 0xa0 0 1 15 0xa1 0 6\n79 2b 00 51 75 61 6e 74 61\n\nRead `Quanta' from FRU at bus=1/addr=0x50/offset=15 at host\n# ipmitool raw 0x2e 2 0x79 0x2b 0x00 1 0 0xa0 0 1 15 0xa1 0 6\n79 2b 00 51 75 61 6e 74 61\n\nKey to bytes\nnetfn 0x2e for OEM extension\ncmd 2 for I2C via IPMI\noem iana number (0x79 0x2b 0x00 for OpenBmc; Google OEN also works)\nreq hdr (bmc bus, request flags)\nwrite step bytes\n * devAndDir 0xa0 =\u003e device addr 0x50, dir = write\n * flags 0\n * parm 1 =\u003e send 1 data byte (data bytes follow step header)\n * data byte 15 selects register 15\n * read step bytes (devAndDir, flags, parm=6 =\u003e read 6 bytes)\n```\n\nHopefully you can see how to modify these commands in simple ways:\n\n- Use a different BMC bus or device address.\n- Change the data byte to select a different starting register, other than 15.\n- Change the read step length to read more/fewer bytes, but note max is 32.\n\nMore advanced ideas\n\n- Skip the read step \u0026 add more data bytes to write to selected address.\n- Zero length read / write step do quick write 1 / 0, respectively\n\n### IPMID OpenBMC I2C Command Extension\n\n- Register handler for OpenBmc I2c Oem Extension requests\n- Handle I2C transfer request\n  - Decode message information\n  - Convert request steps to struct i2c_msg array entries\n    - Adjust M_RCV_LEN steps for IOCTL\n  - Perform I2C_RDWR ioctl on associated I2C bus\n  - Return nonzero completion code upon errors; or\n  - Append all bytes read into one reply upon success\n\n### Prodkernel i2c-via-ipmi Proxy Platform Driver\n\n#### Platform i2c-via-ipmi\n\nPlatform device attributes at /sys/devices/platform/i2c-via-ipmi/${name}\n\n- name - identifies proxy (BMC's i2c bus number)\n\n#### Proxy Operation\n\n##### I2C Adapter Instance\n\n- Host tool performs I/O on this interface\n- Implements master_xfer method\n\n##### IPMI User Instance\n\n- Supports IPMI messaging\n- Implements ipmi_recv_hndl callback\n\n##### I2C master_xfer logic\n\n- Convert struct i2c_msg array to IPMI request\n- Send request \u0026 wait for completion\n\n##### IPMI ipmi_recv_hndl logic\n\n- Check everything possible to ensure this is a reply to our request\n- Copy received bytes to user buffer(s)\n- Declare completion\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenbmc%2Fgoogle-ipmi-i2c","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenbmc%2Fgoogle-ipmi-i2c","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenbmc%2Fgoogle-ipmi-i2c/lists"}