diff --git a/src/elf2kip.c b/src/elf2kip.c index d50cc55..d5b94bb 100644 --- a/src/elf2kip.c +++ b/src/elf2kip.c @@ -315,74 +315,112 @@ int ParseKipConfiguration(const char *json, KipHeader *kip_hdr) { kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 5) | (0x000F)); } } - } else if (!strcmp(type_str, "map")) { - if (cur_cap + 2 > 0x20) { - fprintf(stderr, "Error: Too many capabilities!\n"); + } else if (!strcmp(type_str, "maps")) { + if (!cJSON_IsArray(value)) { + fprintf(stderr, "Maps Capability value must be array!\n"); status = 0; goto PARSE_CAPS_END; } - if (!cJSON_IsObject(value)) { - fprintf(stderr, "Map Capability value must be object!\n"); + const cJSON *cur_map = NULL; + cJSON_ArrayForEach(cur_map, value) { + if (cur_cap + 2 > 0x20) { + fprintf(stderr, "Error: Too many capabilities!\n"); + status = 0; + goto PARSE_CAPS_END; + } + if (!cJSON_IsObject(cur_map)) { + fprintf(stderr, "Maps Capability content value must be object!\n"); + status = 0; + goto PARSE_CAPS_END; + } + + u64 map_address = 0; + u64 map_size = 0; + int is_ro; + int is_io; + if (!cJSON_GetU64(cur_map, "address", &map_address) || + !cJSON_GetU64(cur_map, "size", &map_size) || + !cJSON_GetBoolean(cur_map, "is_ro", &is_ro) || + !cJSON_GetBoolean(cur_map, "is_io", &is_io)) { + status = 0; + goto PARSE_CAPS_END; + } + desc = (u32)((map_address >> 12) & 0x00FFFFFFULL); + desc |= is_ro << 24; + kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 7) | (0x003F)); + + desc = (u32)((map_size >> 12) & 0x00FFFFFFULL); + is_io ^= 1; + desc |= is_io << 24; + kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 7) | (0x003F)); + } + } else if (!strcmp(type_str, "map_pages")) { + if (!cJSON_IsArray(value)) { + fprintf(stderr, "Map Pages Capability value must be array!\n"); status = 0; goto PARSE_CAPS_END; } - u64 map_address = 0; - u64 map_size = 0; - int is_ro; - int is_io; - if (!cJSON_GetU64(value, "address", &map_address) || - !cJSON_GetU64(value, "size", &map_size) || - !cJSON_GetBoolean(value, "is_ro", &is_ro) || - !cJSON_GetBoolean(value, "is_io", &is_io)) { - status = 0; - goto PARSE_CAPS_END; + const cJSON *cur_map_page = NULL; + cJSON_ArrayForEach(cur_map_page, value) { + if (cur_cap + 1 > 0x20) { + fprintf(stderr, "Error: Too many capabilities!\n"); + status = 0; + goto PARSE_CAPS_END; + } + u64 page_address = 0; + if (!cJSON_GetU64FromObjectValue(cur_map_page, &page_address)) { + status = 0; + goto PARSE_CAPS_END; + } + desc = (u32)((page_address >> 12) & 0x00FFFFFFULL); + kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 8) | (0x007F)); } - desc = (u32)((map_address >> 12) & 0x00FFFFFFULL); - desc |= is_ro << 24; - kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 7) | (0x003F)); - - desc = (u32)((map_size >> 12) & 0x00FFFFFFULL); - is_io ^= 1; - desc |= is_io << 24; - kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 7) | (0x003F)); - } else if (!strcmp(type_str, "map_page")) { - if (cur_cap + 1 > 0x20) { - fprintf(stderr, "Error: Too many capabilities!\n"); - status = 0; - goto PARSE_CAPS_END; - } - u64 page_address = 0; - if (!cJSON_GetU64FromObjectValue(value, &page_address)) { - status = 0; - goto PARSE_CAPS_END; - } - desc = (u32)((page_address >> 12) & 0x00FFFFFFULL); - kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 8) | (0x007F)); - } else if (!strcmp(type_str, "irq_pair")) { - if (cur_cap + 1 > 0x20) { - fprintf(stderr, "Error: Too many capabilities!\n"); - status = 0; - goto PARSE_CAPS_END; - } - if (!cJSON_IsArray(value) || cJSON_GetArraySize(value) != 2) { - fprintf(stderr, "Error: IRQ Pairs must have size 2 array value.\n"); + } else if (!strcmp(type_str, "irqs")) { + if (!cJSON_IsArray(value)) { + fprintf(stderr, "Error: IRQs must be in an array.\n"); status = 0; goto PARSE_CAPS_END; } const cJSON *irq = NULL; + u16 lastirq = 0x400; + u16 curirq; cJSON_ArrayForEach(irq, value) { - desc <<= 10; - if (cJSON_IsNull(irq)) { - desc |= 0x3FF; - } else if (cJSON_IsNumber(irq)) { - desc |= ((u16)(irq->valueint)) & 0x3FF; - } else { + if (!cJSON_IsNumber(irq)) { fprintf(stderr, "Failed to parse IRQ value.\n"); status = 0; goto PARSE_CAPS_END; } + curirq = (u16)irq->valueint; + if (curirq > 0x3FF) { + fprintf(stderr, "IRQ should be between 0 and 0x3FF.\n"); + status = 0; + goto PARSE_CAPS_END; + } + + if (lastirq == 0x400) { + /* We have to handle irqs in pair. Remember the first of each pair */ + lastirq = curirq & 0x3FF; + } else if (cur_cap + 1 <= 0x20) { + /* Once we have a pair, store it in the caps */ + desc = (lastirq << 10) | (curirq & 0x3FF); + kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 12) | (0x07FF)); + desc = 0; + lastirq = 0x400; + } else { + fprintf(stderr, "Error: Too many capabilities!\n"); + status = 0; + goto PARSE_CAPS_END; + } + } + /* Handle last value in IRQ array. */ + if (lastirq != 0x400 && cur_cap + 1 <= 0x20) { + desc = (lastirq << 10) | 0x3FF; + kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 12) | (0x07FF)); + } else if (lastirq != 0x400) { + fprintf(stderr, "Error: Too many capabilities!\n"); + status = 0; + goto PARSE_CAPS_END; } - kip_hdr->Capabilities[cur_cap++] = (u32)((desc << 12) | (0x07FF)); } else if (!strcmp(type_str, "application_type")) { if (cur_cap + 1 > 0x20) { fprintf(stderr, "Error: Too many capabilities!\n"); diff --git a/src/npdmtool.c b/src/npdmtool.c index 9b2061f..065fb6b 100644 --- a/src/npdmtool.c +++ b/src/npdmtool.c @@ -478,59 +478,93 @@ int CreateNpdm(const char *json, void **dst, u32 *dst_size) { caps[cur_cap++] = (u32)((desc << 5) | (0x000F)); } } - } else if (!strcmp(type_str, "map")) { - if (!cJSON_IsObject(value)) { - fprintf(stderr, "Map Capability value must be object!\n"); + } else if (!strcmp(type_str, "maps")) { + if (!cJSON_IsArray(value)) { + fprintf(stderr, "Maps Capability value must be array!\n"); status = 0; goto NPDM_BUILD_END; } - u64 map_address = 0; - u64 map_size = 0; - int is_ro; - int is_io; - if (!cJSON_GetU64(value, "address", &map_address) || - !cJSON_GetU64(value, "size", &map_size) || - !cJSON_GetBoolean(value, "is_ro", &is_ro) || - !cJSON_GetBoolean(value, "is_io", &is_io)) { + const cJSON *cur_map = NULL; + cJSON_ArrayForEach(cur_map, value) { + if (!cJSON_IsObject(cur_map)) { + fprintf(stderr, "Maps Capability content value must be object!\n"); + status = 0; + goto NPDM_BUILD_END; + } + u64 map_address = 0; + u64 map_size = 0; + int is_ro; + int is_io; + if (!cJSON_GetU64(cur_map, "address", &map_address) || + !cJSON_GetU64(cur_map, "size", &map_size) || + !cJSON_GetBoolean(cur_map, "is_ro", &is_ro) || + !cJSON_GetBoolean(cur_map, "is_io", &is_io)) { + status = 0; + goto NPDM_BUILD_END; + } + desc = (u32)((map_address >> 12) & 0x00FFFFFFULL); + desc |= is_ro << 24; + caps[cur_cap++] = (u32)((desc << 7) | (0x003F)); + + desc = (u32)((map_size >> 12) & 0x00FFFFFFULL); + is_io ^= 1; + desc |= is_io << 24; + caps[cur_cap++] = (u32)((desc << 7) | (0x003F)); + } + } else if (!strcmp(type_str, "map_pages")) { + if (!cJSON_IsArray(value)) { + fprintf(stderr, "Map Pages Capability value must be array!\n"); status = 0; goto NPDM_BUILD_END; } - desc = (u32)((map_address >> 12) & 0x00FFFFFFULL); - desc |= is_ro << 24; - caps[cur_cap++] = (u32)((desc << 7) | (0x003F)); - - desc = (u32)((map_size >> 12) & 0x00FFFFFFULL); - is_io ^= 1; - desc |= is_io << 24; - caps[cur_cap++] = (u32)((desc << 7) | (0x003F)); - } else if (!strcmp(type_str, "map_page")) { u64 page_address = 0; - if (!cJSON_GetU64FromObjectValue(value, &page_address)) { - status = 0; - goto NPDM_BUILD_END; + const cJSON *cur_map_page = NULL; + cJSON_ArrayForEach(cur_map_page, value) { + if (!cJSON_GetU64FromObjectValue(cur_map_page, &page_address)) { + status = 0; + goto NPDM_BUILD_END; + } + desc = (u32)((page_address >> 12) & 0x00FFFFFFULL); + caps[cur_cap++] = (u32)((desc << 8) | (0x007F)); } - desc = (u32)((page_address >> 12) & 0x00FFFFFFULL); - caps[cur_cap++] = (u32)((desc << 8) | (0x007F)); - } else if (!strcmp(type_str, "irq_pair")) { - if (!cJSON_IsArray(value) || cJSON_GetArraySize(value) != 2) { - fprintf(stderr, "Error: IRQ Pairs must have size 2 array value.\n"); + } else if (!strcmp(type_str, "irqs")) { + if (!cJSON_IsArray(value)) { + fprintf(stderr, "Error: IRQs must be in an array.\n"); status = 0; goto NPDM_BUILD_END; } const cJSON *irq = NULL; + u16 lastirq = 0x400; + u16 curirq; cJSON_ArrayForEach(irq, value) { - desc <<= 10; - if (cJSON_IsNull(irq)) { - desc |= 0x3FF; - } else if (cJSON_IsNumber(irq)) { - desc |= ((u16)(irq->valueint)) & 0x3FF; - } else { + if (!cJSON_IsNumber(irq)) { fprintf(stderr, "Failed to parse IRQ value.\n"); status = 0; goto NPDM_BUILD_END; } + curirq = (u16)irq->valueint; + if (curirq > 0x3FF) { + fprintf(stderr, "IRQ should be between 0 and 0x3FF.\n"); + status = 0; + goto NPDM_BUILD_END; + } + + if (lastirq == 0x400) { + /* We have to handle irqs in pair. Remember the first of each pair */ + lastirq = curirq & 0x3FF; + } else { + /* Once we have a pair, store it in the caps */ + desc = (lastirq << 10) | (curirq & 0x3FF); + caps[cur_cap++] = (u32)((desc << 12) | (0x07FF)); + desc = 0; + lastirq = 0x400; + } + } + /* Handle last value in IRQ array. */ + if (lastirq != 0x400) { + desc = (lastirq << 10) | 0x3FF; + caps[cur_cap++] = (u32)((desc << 12) | (0x07FF)); } - caps[cur_cap++] = (u32)((desc << 12) | (0x07FF)); } else if (!strcmp(type_str, "application_type")) { if (!cJSON_GetU16FromObjectValue(value, (u16 *)&desc)) { status = 0;