| 1 | #include <stdint.h> |
| 2 | #include <stddef.h> |
| 3 | #include <lib/misc.h> |
| 4 | #include <lib/print.h> |
| 5 | |
| 6 | bool verbose = false; |
| 7 | bool quiet = false; |
| 8 | bool serial = false; |
| 9 | bool hash_mismatch_panic = false; |
| 10 | bool measured_boot = false; |
| 11 | |
| 12 | uint8_t bcd_to_int(uint8_t val) { |
| 13 | return (val & 0x0f) + ((val & 0xf0) >> 4) * 10; |
| 14 | } |
| 15 | uint8_t int_to_bcd(uint8_t val) { |
| 16 | return (val % 10) | (val / 10) << 4; |
| 17 | } |
| 18 | |
| 19 | int digit_to_int(char c) { |
| 20 | if (c >= 'a' && c <= 'f') { |
| 21 | return (c - 'a') + 10; |
| 22 | } |
| 23 | if (c >= 'A' && c <= 'F') { |
| 24 | return (c - 'A') + 10; |
| 25 | } |
| 26 | if (c >= '0' && c <= '9'){ |
| 27 | return c - '0'; |
| 28 | } |
| 29 | |
| 30 | return -1; |
| 31 | } |
| 32 | |
| 33 | uint64_t strtoui(const char *s, const char **end, int base) { |
| 34 | uint64_t n = 0; |
| 35 | for (size_t i = 0; ; i++) { |
| 36 | int d = digit_to_int(s[i]); |
| 37 | if (d == -1 || d >= base) { |
| 38 | if (end != NULL) |
| 39 | *end = &s[i]; |
| 40 | break; |
| 41 | } |
| 42 | uint64_t mul_result = CHECKED_MUL(n, base, ({ |
| 43 | if (end != NULL) |
| 44 | *end = &s[i]; |
| 45 | return UINT64_MAX; |
| 46 | })); |
| 47 | n = CHECKED_ADD(mul_result, d, ({ |
| 48 | if (end != NULL) |
| 49 | *end = &s[i]; |
| 50 | return UINT64_MAX; |
| 51 | })); |
| 52 | } |
| 53 | return n; |
| 54 | } |
| 55 | |
| 56 | bool get_absolute_path(char *path_ptr, const char *path, const char *pwd, size_t size) { |
| 57 | char *orig_ptr = path_ptr; |
| 58 | char *end_ptr = path_ptr + size - 1; |
| 59 | |
| 60 | if (size == 0) return false; |
| 61 | |
| 62 | if (!*path) { |
| 63 | size_t pwd_len = strlen(pwd); |
| 64 | if (pwd_len >= size) return false; |
| 65 | memcpy(path_ptr, pwd, pwd_len + 1); |
| 66 | return true; |
| 67 | } |
| 68 | |
| 69 | if (*path != '/') { |
| 70 | size_t pwd_len = strlen(pwd); |
| 71 | if (pwd_len >= size) return false; |
| 72 | memcpy(path_ptr, pwd, pwd_len + 1); |
| 73 | path_ptr += pwd_len; |
| 74 | } else { |
| 75 | *path_ptr = '/'; |
| 76 | path_ptr++; |
| 77 | path++; |
| 78 | } |
| 79 | |
| 80 | goto first_run; |
| 81 | |
| 82 | for (;;) { |
| 83 | switch (*path) { |
| 84 | case '/': |
| 85 | path++; |
| 86 | first_run: |
| 87 | if (*path == '/') continue; |
| 88 | if ((!strncmp(path, ".\0", 2)) |
| 89 | || (!strncmp(path, "./\0", 3))) { |
| 90 | goto term; |
| 91 | } |
| 92 | if ((!strncmp(path, "..\0", 3)) |
| 93 | || (!strncmp(path, "../\0", 4))) { |
| 94 | while (path_ptr > orig_ptr && *path_ptr != '/') path_ptr--; |
| 95 | if (path_ptr == orig_ptr) path_ptr++; |
| 96 | goto term; |
| 97 | } |
| 98 | if (!strncmp(path, "../", 3)) { |
| 99 | while (path_ptr > orig_ptr && *path_ptr != '/') path_ptr--; |
| 100 | if (path_ptr == orig_ptr) path_ptr++; |
| 101 | path += 2; |
| 102 | *path_ptr = 0; |
| 103 | continue; |
| 104 | } |
| 105 | if (!strncmp(path, "./", 2)) { |
| 106 | path += 1; |
| 107 | continue; |
| 108 | } |
| 109 | if (path_ptr > orig_ptr && ((path_ptr - 1) != orig_ptr) && (*(path_ptr - 1) != '/')) { |
| 110 | if (path_ptr >= end_ptr) return false; |
| 111 | *path_ptr = '/'; |
| 112 | path_ptr++; |
| 113 | } |
| 114 | continue; |
| 115 | case '\0': |
| 116 | term: |
| 117 | if (path_ptr > orig_ptr && (*(path_ptr - 1) == '/') && ((path_ptr - 1) != orig_ptr)) |
| 118 | path_ptr--; |
| 119 | *path_ptr = 0; |
| 120 | return true; |
| 121 | default: |
| 122 | if (path_ptr >= end_ptr) return false; |
| 123 | *path_ptr = *path; |
| 124 | path++; |
| 125 | path_ptr++; |
| 126 | continue; |
| 127 | } |
| 128 | } |
| 129 | } |