avb_cmdline.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <string.h>
  32. #include <pal_typedefs.h>
  33. #include <pal_log.h>
  34. #include <pal_assert.h>
  35. #include <avb_cmdline.h>
  36. #include <verified_boot_error.h>
  37. #define CMDLINE_TAG "[cmdline]"
  38. #define MAX_ENTRIES (16)
  39. #define INIT (0)
  40. #define IS_KEY (1)
  41. #define IS_VALUE (2)
  42. #define IS_VALUE_IN_QUOTATION (3)
  43. #define KEY_MATCH (0)
  44. #define KEY_NOT_MATCH (1)
  45. struct cmdline_entry {
  46. char key[MAX_KEY_SZ + 1];
  47. char value[MAX_VALUE_SZ + 1];
  48. };
  49. static struct cmdline_entry g_cmdline_buf[MAX_ENTRIES];
  50. static uint32_t g_cur_cmdline_entry_idx = 0;
  51. static uint32_t is_key_match(char *in, uint32_t in_sz, const char *key)
  52. {
  53. uint32_t match = KEY_NOT_MATCH;
  54. if (in == NULL)
  55. return KEY_NOT_MATCH;
  56. if (key == NULL)
  57. return KEY_NOT_MATCH;
  58. if (strlen(key) != in_sz)
  59. return KEY_NOT_MATCH;
  60. if (0 == memcmp(in, key, in_sz))
  61. match = KEY_MATCH;
  62. return match;
  63. }
  64. uint32_t avb_get_cmdline(const char *key, char *output, uint32_t output_sz)
  65. {
  66. uint32_t ret = ERR_AVB_CMDLINE_ENTRY_NOT_FOUND;
  67. uint32_t i = 0;
  68. uint32_t value_sz = 0;
  69. if (key == NULL)
  70. return ERR_AVB_INVALID_KEY_BUF;
  71. if (output == NULL)
  72. return ERR_AVB_INVALID_OUTPUT_BUF;
  73. for (i = 0; i < MAX_ENTRIES; i++) {
  74. if (g_cmdline_buf[i].key[0] == '\0')
  75. break;
  76. if (KEY_MATCH == is_key_match(g_cmdline_buf[i].key,
  77. strlen(g_cmdline_buf[i].key),
  78. key)) {
  79. value_sz = strlen(g_cmdline_buf[i].value);
  80. if (value_sz == 0) {
  81. return ERR_AVB_INVALID_VALUE_SZ;
  82. } else {
  83. if (output_sz < value_sz + 1)
  84. return ERR_AVB_INVALID_OUTPUT_BUF;
  85. memcpy(output, g_cmdline_buf[i].value, value_sz);
  86. output[value_sz] = '\0';
  87. }
  88. return STATUS_OK;
  89. }
  90. }
  91. return ret;
  92. }
  93. /* extract key/value from cmdline and set them into device tree later */
  94. uint32_t avb_extract_from_cmdline(char *in, uint32_t in_sz, const char *key)
  95. {
  96. uint32_t ret = 0;
  97. uint32_t i = 0;
  98. uint32_t j = 0;
  99. uint32_t cur_state = INIT;
  100. uint32_t key_off_s = 0;
  101. uint32_t key_off_e = 0;
  102. uint32_t key_sz = 0;
  103. uint32_t val_off_s = 0;
  104. uint32_t val_off_e = 0;
  105. uint32_t val_sz = 0;
  106. uint32_t key_match = KEY_NOT_MATCH;
  107. uint32_t next_off = 0;
  108. if (in == NULL)
  109. return ERR_AVB_INVALID_INPUT_BUF;
  110. if (key == NULL)
  111. return ERR_AVB_INVALID_KEY_BUF;
  112. if ((strlen(key) > in_sz) || (strlen(key) > strlen(in)))
  113. return ERR_AVB_INVALID_KEY_BUF;
  114. while (i <= in_sz) {
  115. if (in[i] == ' ' || i == in_sz) {
  116. switch (cur_state) {
  117. case IS_KEY:
  118. /* end of key is found and there is no
  119. * value for this key */
  120. key_off_e = i - 1;
  121. key_sz = key_off_e - key_off_s + 1;
  122. /* check if this is the key we want */
  123. key_match = is_key_match(in + key_off_s, key_sz, key);
  124. if (key_match == KEY_MATCH) {
  125. if (key_sz > MAX_KEY_SZ)
  126. return ERR_AVB_INVALID_KEY_BUF;
  127. memcpy(g_cmdline_buf[g_cur_cmdline_entry_idx].key,
  128. in + key_off_s,
  129. key_sz);
  130. /* find the first non-space character offset after key_off_e */
  131. next_off = key_off_e + 1;
  132. while (next_off < in_sz && in[next_off] == ' ') next_off++;
  133. for (j = 0; j < in_sz - next_off; j++) {
  134. in[key_off_s + j] = in[next_off + j];
  135. in[next_off + j] = '\0';
  136. }
  137. in[key_off_s + j] = '\0';
  138. g_cur_cmdline_entry_idx++;
  139. return 0;
  140. }
  141. cur_state = INIT;
  142. break;
  143. case IS_VALUE:
  144. /* end of value is found */
  145. val_off_e = i - 1;
  146. val_sz = val_off_e - val_off_s + 1;
  147. if (key_match == KEY_MATCH) {
  148. if (val_sz > MAX_VALUE_SZ)
  149. return ERR_AVB_INVALID_VALUE_SZ;
  150. memcpy(g_cmdline_buf[g_cur_cmdline_entry_idx].value,
  151. in + val_off_s,
  152. val_sz);
  153. /* find the first non-space character offset after val_off_e */
  154. next_off = val_off_e + 1;
  155. while (next_off < in_sz && in[next_off] == ' ') next_off++;
  156. for (j = 0; j < in_sz - next_off; j++) {
  157. in[key_off_s + j] = in[next_off + j];
  158. in[next_off + j] = '\0';
  159. }
  160. in[key_off_s + j] = '\0';
  161. g_cur_cmdline_entry_idx++;
  162. return 0;
  163. }
  164. cur_state = INIT;
  165. break;
  166. case INIT:
  167. case IS_VALUE_IN_QUOTATION:
  168. /* ignore */
  169. default:
  170. break;
  171. }
  172. } else if (in[i] == '=') {
  173. switch (cur_state) {
  174. case IS_KEY:
  175. /* end of key is found and there is
  176. * value for this key */
  177. key_off_e = i - 1;
  178. key_sz = key_off_e - key_off_s + 1;
  179. /* check if this is the key we want */
  180. key_match = is_key_match(in + key_off_s, key_sz, key);
  181. if (key_match == KEY_MATCH) {
  182. if (key_sz > MAX_KEY_SZ)
  183. return ERR_AVB_INVALID_VALUE_SZ;
  184. memcpy(g_cmdline_buf[g_cur_cmdline_entry_idx].key,
  185. in + key_off_s,
  186. key_sz);
  187. }
  188. cur_state = IS_VALUE;
  189. val_off_s = i + 1;
  190. break;
  191. case INIT:
  192. case IS_VALUE:
  193. case IS_VALUE_IN_QUOTATION:
  194. /* ignore */
  195. default:
  196. break;
  197. }
  198. } else if (in[i] == '\"') {
  199. if (cur_state == IS_VALUE) {
  200. val_off_s = i;
  201. cur_state = IS_VALUE_IN_QUOTATION;
  202. } else if (cur_state == IS_VALUE_IN_QUOTATION) {
  203. val_off_e = i;
  204. val_sz = val_off_e - val_off_s + 1;
  205. if (key_match == KEY_MATCH) {
  206. if (val_sz > MAX_VALUE_SZ)
  207. return ERR_AVB_INVALID_VALUE_SZ;
  208. memcpy(g_cmdline_buf[g_cur_cmdline_entry_idx].value,
  209. in + val_off_s,
  210. val_sz);
  211. /* find the first non-space character offset after key_off_e */
  212. next_off = val_off_e + 1;
  213. while (next_off < in_sz && in[next_off] == ' ') next_off++;
  214. if (next_off != in_sz)
  215. memcpy(in + key_off_s, in + next_off, in_sz - next_off);
  216. memset(in + key_off_s + in_sz - next_off,
  217. '\0',
  218. next_off - key_off_s);
  219. g_cur_cmdline_entry_idx++;
  220. return 0;
  221. }
  222. cur_state = INIT;
  223. } else {
  224. return ERR_AVB_INVALID_CMDLINE_FMT;
  225. }
  226. } else {
  227. switch (cur_state) {
  228. case INIT:
  229. ASSERT(g_cur_cmdline_entry_idx < MAX_ENTRIES);
  230. if (g_cur_cmdline_entry_idx == MAX_ENTRIES) {
  231. pal_log_err("%s overflow", CMDLINE_TAG);
  232. return ERR_AVB_CMDLINE_OVERFLOW;
  233. }
  234. key_off_s = i;
  235. cur_state = IS_KEY;
  236. break;
  237. case IS_KEY:
  238. case IS_VALUE:
  239. case IS_VALUE_IN_QUOTATION:
  240. /* ignore */
  241. default:
  242. break;
  243. }
  244. }
  245. i++;
  246. }
  247. return ret;
  248. }