flash_otp_write.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * flash_otp_write.c -- write One-Time-Program data
  3. */
  4. #define PROGRAM_NAME "flash_otp_write"
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <fcntl.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <errno.h>
  11. #include <sys/types.h>
  12. #include <sys/ioctl.h>
  13. #include <common.h>
  14. #include <mtd/mtd-user.h>
  15. static ssize_t xread(int fd, void *buf, size_t count)
  16. {
  17. ssize_t ret, done = 0;
  18. retry:
  19. ret = read(fd, buf + done, count - done);
  20. if (ret < 0)
  21. return ret;
  22. done += ret;
  23. if (ret == 0 /* EOF */ || done == count)
  24. return done;
  25. else
  26. goto retry;
  27. }
  28. int main(int argc,char *argv[])
  29. {
  30. int fd, val, ret, size, wrote, len;
  31. mtd_info_t mtdInfo;
  32. off_t offset;
  33. char *p, buf[2048];
  34. if (argc != 4 || strcmp(argv[1], "-u")) {
  35. fprintf(stderr, "Usage: %s -u <device> <offset>\n", PROGRAM_NAME);
  36. fprintf(stderr, "the raw data to write should be provided on stdin\n");
  37. fprintf(stderr, "CAUTION! ONCE SET TO 0, OTP DATA BITS CAN'T BE ERASED!\n");
  38. return EINVAL;
  39. }
  40. fd = open(argv[2], O_WRONLY);
  41. if (fd < 0) {
  42. perror(argv[2]);
  43. return errno;
  44. }
  45. val = MTD_OTP_USER;
  46. ret = ioctl(fd, OTPSELECT, &val);
  47. if (ret < 0) {
  48. perror("OTPSELECT");
  49. return errno;
  50. }
  51. if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
  52. perror("MEMGETINFO");
  53. return errno;
  54. }
  55. offset = (off_t)strtoull(argv[3], &p, 0);
  56. if (argv[3][0] == 0 || *p != 0) {
  57. fprintf(stderr, "%s: bad offset value\n", PROGRAM_NAME);
  58. return ERANGE;
  59. }
  60. if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
  61. perror("lseek()");
  62. return errno;
  63. }
  64. printf("Writing OTP user data on %s at offset 0x%llx\n", argv[2], (unsigned long long)offset);
  65. if (mtd_type_is_nand_user(&mtdInfo))
  66. len = mtdInfo.writesize;
  67. else
  68. len = 256;
  69. if (len > sizeof(buf)) {
  70. printf("huh, writesize (%d) bigger than buffer (%zu)\n",
  71. len, sizeof(buf));
  72. return ENOMEM;
  73. }
  74. wrote = 0;
  75. while ((size = xread(0, buf, len))) {
  76. if (size < 0) {
  77. perror("read()");
  78. return errno;
  79. }
  80. p = buf;
  81. while (size > 0) {
  82. if (mtd_type_is_nand_user(&mtdInfo)) {
  83. /* Fill remain buffers with 0xff */
  84. memset(buf + size, 0xff, mtdInfo.writesize - size);
  85. size = mtdInfo.writesize;
  86. }
  87. ret = write(fd, p, size);
  88. if (ret < 0) {
  89. perror("write()");
  90. return errno;
  91. }
  92. if (ret == 0) {
  93. printf("write() returned 0 after writing %d bytes\n", wrote);
  94. return 0;
  95. }
  96. p += ret;
  97. wrote += ret;
  98. size -= ret;
  99. }
  100. }
  101. printf("Wrote %d bytes of OTP user data\n", wrote);
  102. return 0;
  103. }