-
-
Notifications
You must be signed in to change notification settings - Fork 64
hisi: read the V5 die ID from the OTP shadow #188
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,17 +97,22 @@ static void print_chip_temperature() { | |
| } | ||
|
|
||
| static void print_serial() { | ||
| char serial[512]; | ||
| char serial[512] = {0}; | ||
| bool found = false; | ||
|
|
||
| const char *vendor = getchipvendor(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pre-existing, but this PR puts One |
||
| if (strstr(vendor, VENDOR_HISI) || strstr(vendor, VENDOR_GOKE)) | ||
| hisi_ev300_get_die_id(serial, sizeof serial); | ||
| found = hisi_get_die_id(serial, sizeof serial); | ||
| #ifdef IPCHW_VENDOR_SSTAR | ||
| if (strstr(vendor, VENDOR_SSTAR)) | ||
| sstar_get_die_id(serial, sizeof serial); | ||
| found = sstar_get_die_id(serial, sizeof serial); | ||
| #endif | ||
|
|
||
| if (!serial) | ||
| // The test used to be `if (!serial)`, the address of a stack array, which | ||
| // is never null -- a chip with no reader printed whatever the stack held. | ||
| // Provisioning scripts derive a MAC from this, so a miss has to be silent | ||
| // on stdout and non-zero on exit. | ||
| if (!found || !*serial) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth a line in the description: on master That is what |
||
| exit(EXIT_FAILURE); | ||
| puts(serial); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
|
|
||
|
|
||
| bool hisi_ev300_get_die_id(char *buf, ssize_t len); | ||
| bool hisi_get_die_id(char *buf, ssize_t len); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two small things now that there is a single entry point:
|
||
| void hisi_vi_information(sensor_ctx_t *ctx); | ||
| unsigned long hisi_totalmem(unsigned long *media_mem); | ||
| bool hisi_detect_cpu(char *chip_name, uint32_t SC_CTRL_base); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -714,6 +714,69 @@ bool hisi_ev300_get_die_id(char *buf, ssize_t len) { | |
| return true; | ||
| } | ||
|
|
||
| /* Per-die identity on V5 (HISI_OT). | ||
| * | ||
| * V5 has no counterpart to the V4 die-ID block at 0x12020400. The vendor keeps | ||
| * the die ID in OTP and reaches it through a bootrom call (otp_get_die_id() in | ||
| * gsl/drivers/share_drivers/share_drivers.c), but every OTP row is also | ||
| * shadowed into a register window at the same offset it occupies in OTP, so | ||
| * the 16 bytes of OTP_DIE_ID appear at OTP_SHADOW_BASE + 0xF0. Offsets from | ||
| * Hi3516CV610_SDK_V1.0.2.0: | ||
| * .../bsp/components/gsl/drivers/otp/otp.h OTP_DIE_ID 0xF0, 16 bytes | ||
| * .../bsp/components/gsl/include/platform.h OTP_SHADOW_BASE = 0x101E0000 | ||
| * | ||
| * The window is readable from the non-secure side: the OEM's own hwconf.ko | ||
| * ioremaps OTP_SHADOW_BASE + 0x10C (OTP_VERSION_ID_REG, the ATE chip version) | ||
| * from an ordinary kernel module. | ||
| * | ||
| * Bytes are emitted in OTP order. The shadow words are little-endian, so byte | ||
| * i of what otp_get_die_id() would hand back is word[i / 4] >> (8 * (i % 4)). | ||
| */ | ||
| #define V5_OTP_SHADOW_BASE 0x101E0000u | ||
| #define V5_OTP_DIE_ID 0xF0 | ||
| #define V5_DIE_ID_WORDS 4 | ||
|
|
||
| static bool hisi_ot_get_die_id(char *buf, ssize_t len) { | ||
| if (len < V5_DIE_ID_WORDS * 8 + 1) | ||
| return false; | ||
|
|
||
| uint32_t id[V5_DIE_ID_WORDS]; | ||
| uint32_t any_bit_set = 0; | ||
| uint32_t all_bits_set = 0xFFFFFFFF; | ||
| for (int i = 0; i < V5_DIE_ID_WORDS; i++) { | ||
| if (!mem_reg(V5_OTP_SHADOW_BASE + V5_OTP_DIE_ID + i * 4, &id[i], | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocking. This base is verified on one CV608, and the SDK it comes from covers CV608/CV610/CV613, but it runs on every Two failure modes if
Suggest gating the reader on the chip IDs the CV610 SDK covers until a DV500 or 3519DV500 has been measured. The read is harmless, so this is the whole test: for a in 0x101E00F0 0x101E00F4 0x101E00F8 0x101E00FC 0x101E010C; do devmem $a 32; done
|
||
| OP_READ)) | ||
| return false; | ||
| any_bit_set |= id[i]; | ||
| all_bits_set &= id[i]; | ||
| } | ||
|
|
||
| // An unfused or unreadable row reads all-zeroes or all-ones. Neither is an | ||
| // identity, and callers turn this string into a MAC address -- handing one | ||
| // out would give every board in a fleet the same address, so fail instead. | ||
| if (!any_bit_set || all_bits_set == 0xFFFFFFFF) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This combines all four words, so a shadow that reads e.g. Rejecting a 16-byte value whose bytes are all |
||
| return false; | ||
|
|
||
| char *ptr = buf; | ||
| for (int i = 0; i < V5_DIE_ID_WORDS; i++) | ||
| for (int b = 0; b < 4; b++) | ||
| ptr += snprintf(ptr, buf + len - ptr, "%02x", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: sixteen |
||
| (id[i] >> (8 * b)) & 0xFF); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool hisi_get_die_id(char *buf, ssize_t len) { | ||
| switch (chip_generation) { | ||
| case HISI_V4: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The V4 arm skips the all-zero/all-ones rejection that the V5 arm gets at line 757. Since the invariant this PR introduces is "callers derive a MAC from this", the check belongs here in the dispatcher so both arms honour it. |
||
| return hisi_ev300_get_die_id(buf, len); | ||
| case HISI_OT: | ||
| return hisi_ot_get_die_id(buf, len); | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| #define CV300_ISP_AF_CFG_ADDR 0x12200 | ||
| struct CV300_ISP_AF_CFG { | ||
| bool en : 1; | ||
|
|
@@ -927,7 +990,7 @@ struct PT_OFFSET { | |
|
|
||
| void hisi_chip_properties(cJSON *j_inner) { | ||
| char buf[1024]; | ||
| if (hisi_ev300_get_die_id(buf, sizeof buf)) { | ||
| if (hisi_get_die_id(buf, sizeof buf)) { | ||
| ADD_PARAM("id", buf); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the zero-fill and the
!*serialtest are redundant withfound. Every reader writes at least 12 chars before returning true and returns false on every failure path, soif (!found)with a plainchar serial[512]is behaviourally identical, and it makes clear which signal is authoritative.The comment at 111-114 narrates the removed bug. The one sentence worth keeping in code is the last one (provisioning derives a MAC, so a miss must be silent on stdout and non-zero on exit); the rest belongs in the commit message.