昨天还说搞搞uboot,又搞搞MFC。今天又搞搞UBI。
有某个平台,使用UBI系统,工厂烧录回来的样片跑起来有问题,然后启动紧急预案。大有派我去某部门的意向——那个部门其实是单独在某地方,离公司不远,10多公里的路程,打的很快就到了。后面我坚持了远程操作的方法,手把手打字叫某兄弟怎么输入命令,最终找到一个临时解决方法。
闲话不多说,出现问题的提示如下:
1 2
| ubiformat: warning!: 4 of 40 eraseblocks contain non-ubifs data ubiformat: continue? (yes/no)
|
然后ubiformat等待用户输入yes,但测试时不可能手工输入,而且假如有N台设备出现这种情况,不可能一一输入的。程序死等,结果是内核狗超时设备复位。查代码,发现ubiformat有个y参数,强制认为所有的输入是yes,从而继续执行。后来想想,可以可能是没有进行擦除,导致检测失败。继续找代码,定位到一个libscan.c的地方:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr)); if (ret < 0) goto out_ec; if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) { if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) { si->empty_cnt += 1; si->ec[eb] = EB_EMPTY; if (v) printf(": empty\n"); } else { si->alien_cnt += 1; si->ec[eb] = EB_ALIEN; if (v) printf(": alien\n"); } continue; }
|
判断很简单,如果有某个数据(此时的我,对UBI了解不多,只能说“数据”)是全1的,就表示空块,EB_EMPTY,否则就标志为alien(非UBI块)。当有非UBI块时,就会报上面的问题。
(注:后来听说是工厂某兄弟没有把母片内容全部拷贝完。有这个可能,因为出错的分区位于flash很后面,而他们是直接拷贝的,有可能没有进行擦除操作,导致不是所有的数据都是1)
回到本文的正文,其实本文是想写写怎么和用户进行交互,用到哪些函数的。
用法很简单,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| typedef int bool; #define true 1 #define false 0 /** * prompt the user for confirmation */ static inline int prompt(const char *msg, int def) { char *line = NULL; size_t len; int ret = def; do { printf("%s (%c/%c) ", msg, def ? 'Y' : 'y', def ? 'n' : 'N'); fflush(stdout); while (getline(&line, &len, stdin) == -1) { printf("failed to read prompt; assuming '%s'\n", def ? "yes" : "no"); break; } if (strcmp("\n", line) != 0) { switch (rpmatch(line)) { case 0: ret = false; break; case 1: ret = true; break; case -1: puts("unknown response; please try again"); continue; } } break; } while (1); printf("[debug] you input: %s\n", line); free(line); return ret; } // 当输入为no或n时,返回1 static int want_exit(void) { return prompt("continue?", false) == true ? 0 : 1; } // 当输入yes或y时,返回1 static int answer_is_yes(const char *msg) { return prompt(msg ? : "continue?", false); } // 当输入为no或n时,返回1 // 用途:判断返回值,当返回1时,说明是否定的操作,出错处理或退出 static int answer_is_no(const char *msg) { return prompt(msg, false) == true ? 0 : 1; } void test4() { int ret = 0; printf("test for input ...\n"); ret = want_exit(); //ret = answer_is_yes("mark it as bad?"); //ret = answer_is_no("the answer will be no."); printf("return: %d\n", ret); }
|
我直接抄mtd-utils,稍改了一下。这个项目使用GPL,我贴出来,也当是遵循GPL了。
迟,记于2014.05.30