/* * This code was written by Mychaela Falconia * who refuses to claim copyright on it and has released it as public domain * instead. NO rights reserved, all rights relinquished. * * Tweaked (coding style changes) by Vadim Yanitskiy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include #include #include #include #include struct record_hdr { uint16_t valid_flag; uint16_t type; uint16_t native_len; uint16_t rounded_len; }; static void apply_levels(struct txcal_tx_level *levels_table, uint16_t *compal_data, unsigned start_level, unsigned num_levels) { unsigned n; for (n = 0; n < num_levels; n++) levels_table[start_level + n].apc = *compal_data++; } void read_compal_factory_records(uint32_t flash_addr) { struct record_hdr *hdr; void *p, *sector_end; unsigned p_incr; void *payload; printf("Analyzing factory records sector " "at 0x%" PRIx32 "\n", flash_addr); p = (void *) flash_addr; sector_end = p + 0x2000; for (; p < sector_end; p += p_incr) { if ((sector_end - p) < 12) break; hdr = (struct record_hdr *)p; if (hdr->valid_flag == 0xFFFF) /* blank flash */ break; if (hdr->native_len > hdr->rounded_len) { printf("Bad record at 0x%" PRIx32 ": native length " "> rounded length\n", (uint32_t) p); return; } if (hdr->rounded_len & 3) { printf("Bad record at 0x%" PRIx32 ": rounded length " "is not aligned to 4\n", (uint32_t) p); return; } p_incr = hdr->rounded_len + 8; if (p_incr > (sector_end - p)) { printf("Bad record at 0x%" PRIx32 ": rounded length " "spills past the end of the sector\n", (uint32_t) p); return; } if (hdr->valid_flag != 0x000C) continue; payload = (void *)(hdr + 1); switch (hdr->type) { case 0x0000: if (hdr->native_len != 0x94) break; if (*(uint32_t *)(payload + 0x5C) != 0xAA) break; printf("Found 900 MHz band calibration record at " "0x%" PRIx32 ", applying\n", (uint32_t) p); apply_levels(rf_tx_levels_900, payload + 0x60, 5, 15); break; case 0x0001: if (hdr->native_len != 0xC8) break; if (*(uint32_t *)(payload + 0x7C) != 0xAA) break; printf("Found 1800 MHz band calibration record at " "0x%" PRIx32 ", applying\n", (uint32_t) p); apply_levels(rf_tx_levels_1800, payload + 0x80, 0, 16); break; case 0x0002: if (hdr->native_len != 0xB4) break; if (*(uint32_t *)(payload + 0x70) != 0xAA) break; printf("Found 1900 MHz band calibration record at " "0x%" PRIx32 ", applying\n", (uint32_t) p); apply_levels(rf_tx_levels_1900, payload + 0x74, 0, 16); break; case 0x0018: if (hdr->native_len != 0x88) break; if (*(uint32_t *)(payload + 0x54) != 0xAA) break; printf("Found 850 MHz band calibration record at " "0x%" PRIx32 ", applying\n", (uint32_t) p); apply_levels(rf_tx_levels_850, payload + 0x58, 5, 15); break; } } }