vita-toolchain

git clone https://git.neptards.moe/neptards/vita-toolchain.git
Log | Files | Refs | README | LICENSE

vita-import-parse.c (9438B)


      1 #include <string.h>
      2 #include <stdlib.h>
      3 #include "vita-import.h"
      4 #include "yamltree.h"
      5 #include "yamltreeutil.h"
      6 #include "sha256.h"
      7 
      8 int process_import_functions(yaml_node *parent, yaml_node *child, vita_imports_module_t *library) {
      9 	if (!is_scalar(parent)) {
     10 		fprintf(stderr, "error: line: %zd, column: %zd, expecting function to be scalar, got '%s'.\n"
     11 			, parent->position.line
     12 			, parent->position.column
     13 			, node_type_str(parent));
     14 		
     15 		return -1;
     16 	}
     17 	
     18 	yaml_scalar *key = &parent->data.scalar;
     19 		
     20 	// create an export symbol for this function
     21 	vita_imports_stub_t *symbol = vita_imports_stub_new(key->value,0);
     22 		
     23 	if (!is_scalar(child)) {
     24 		fprintf(stderr, "error: line: %zd, column: %zd, expecting function value to be scalar, got '%s'.\n"
     25 			, child->position.line
     26 			, child->position.column
     27 			, node_type_str(child));
     28 		
     29 		return -1;
     30 	}
     31 	
     32 	if (process_32bit_integer(child, &symbol->NID) < 0) {
     33 		fprintf(stderr, "error: line: %zd, column: %zd, could not convert function nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value);
     34 		return -1;
     35 	}
     36 	// append to list
     37 	library->functions = realloc(library->functions, (library->n_functions+1)*sizeof(vita_imports_stub_t*));
     38 	library->functions[library->n_functions++] = symbol;
     39 	
     40 	return 0;
     41 }
     42 
     43 int process_import_variables(yaml_node *parent, yaml_node *child, vita_imports_module_t *library) {
     44 	if (!is_scalar(parent)) {
     45 		fprintf(stderr, "error: line: %zd, column: %zd, expecting variable to be scalar, got '%s'.\n"
     46 			, parent->position.line
     47 			, parent->position.column
     48 			, node_type_str(parent));
     49 		
     50 		return -1;
     51 	}
     52 	
     53 	yaml_scalar *key = &parent->data.scalar;
     54 		
     55 	// create an export symbol for this variable
     56 	vita_imports_stub_t *symbol = vita_imports_stub_new(key->value,0);
     57 			
     58 	if (!is_scalar(child)) {
     59 		fprintf(stderr, "error: line: %zd, column: %zd, expecting variable value to be scalar, got '%s'.\n"
     60 			, child->position.line
     61 			, child->position.column
     62 			, node_type_str(child));
     63 		
     64 		return -1;
     65 	}
     66 	
     67 	if (process_32bit_integer(child, &symbol->NID) < 0) {
     68 		fprintf(stderr, "error: line: %zd, column: %zd, could not convert variable nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value);
     69 		return -1;
     70 	}
     71 	// append to list
     72 	library->variables = realloc(library->variables, (library->n_variables+1)*sizeof(vita_imports_stub_t*));
     73 	library->variables[library->n_variables++] = symbol;
     74 	
     75 	return 0;
     76 }
     77 
     78 int process_library(yaml_node *parent, yaml_node *child, vita_imports_module_t *library) {
     79 	if (!is_scalar(parent)) {
     80 		fprintf(stderr, "error: line: %zd, column: %zd, expecting library key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent));
     81 		return -1;
     82 	}
     83 	
     84 	yaml_scalar *key = &parent->data.scalar;
     85 	
     86 	if (strcmp(key->value, "kernel") == 0) {
     87 		if (!is_scalar(child)) {
     88 			fprintf(stderr, "error: line: %zd, column: %zd, expecting library syscall flag to be scalar, got '%s'.\n", child->position.line, child->position.column, node_type_str(child));
     89 			return -1;
     90 		}
     91 		
     92 		if (process_bool(child, &library->is_kernel) < 0) {
     93 			fprintf(stderr, "error: line: %zd, column: %zd, could not convert library flag to boolean, got '%s'. expected 'true' or 'false'.\n", child->position.line, child->position.column, child->data.scalar.value);
     94 			return -1;
     95 		}
     96 	}
     97 	else if (strcmp(key->value, "functions") == 0) {
     98 		if (yaml_iterate_mapping(child, (mapping_functor)process_import_functions, library) < 0)
     99 			return -1;
    100 	}
    101 	else if (strcmp(key->value, "variables") == 0) {
    102 		if (yaml_iterate_mapping(child, (mapping_functor)process_import_variables, library) < 0)
    103 			return -1;
    104 	}
    105 	else if (strcmp(key->value, "nid") == 0) {
    106 		if (!is_scalar(child)) {
    107 			fprintf(stderr, "error: line: %zd, column: %zd, expecting library nid to be scalar, got '%s'.\n", child->position.line, child->position.column, node_type_str(child));
    108 			return -1;
    109 		}
    110 		
    111 		if (process_32bit_integer(child, &library->NID) < 0) {
    112 			fprintf(stderr, "error: line: %zd, column: %zd, could not convert library nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value);
    113 			return -1;
    114 		}
    115 	}
    116 	else {
    117 		fprintf(stderr, "error: line: %zd, column: %zd, unrecognised library key '%s'.\n", child->position.line, child->position.column, key->value);
    118 		return -1;
    119 	}
    120 	
    121 	return 0;
    122 }
    123 
    124 int process_libraries(yaml_node *parent, yaml_node *child, vita_imports_lib_t *import) {
    125 	if (!is_scalar(parent)) {
    126 		fprintf(stderr, "error: line: %zd, column: %zd, expecting library key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent));
    127 		return -1;
    128 	}
    129 	
    130 	yaml_scalar *key = &parent->data.scalar;
    131 	
    132 	vita_imports_module_t *library = vita_imports_module_new("",false,0,0,0);
    133 	
    134 	// default values
    135 	library->name = strdup(key->value);
    136 
    137 	if (yaml_iterate_mapping(child, (mapping_functor)process_library, library) < 0)
    138 		return -1;
    139 
    140 	import->modules = realloc(import->modules, (import->n_modules+1)*sizeof(vita_imports_module_t*));
    141 	import->modules[import->n_modules++] = library;
    142 		
    143 	return 0;
    144 }
    145 
    146 int process_import(yaml_node *parent, yaml_node *child, vita_imports_lib_t *import) {
    147 	if (!is_scalar(parent)) {
    148 		fprintf(stderr, "error: line: %zd, column: %zd, expecting module key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent));
    149 		return -1;
    150 	}
    151 	
    152 	yaml_scalar *key = &parent->data.scalar;
    153 
    154 	if (strcmp(key->value, "nid") == 0) {
    155 		if (!is_scalar(child)) {
    156 			fprintf(stderr, "error: line: %zd, column: %zd, expecting module nid to be scalar, got '%s'.\n", child->position.line, child->position.column, node_type_str(child));
    157 			return -1;
    158 		}
    159 		
    160 		if (process_32bit_integer(child, &import->NID) < 0) {
    161 			fprintf(stderr, "error: line: %zd, column: %zd, could not convert module nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value);
    162 			return -1;
    163 		}
    164 	}
    165 	else if (strcmp(key->value, "libraries") == 0) {
    166 			
    167 		if (yaml_iterate_mapping(child, (mapping_functor)process_libraries, import) < 0)
    168 			return -1;
    169 
    170 	}
    171 	else {
    172 		fprintf(stderr, "error: line: %zd, column: %zd, unrecognised module key '%s'.\n", child->position.line, child->position.column, key->value);
    173 		return -1;
    174 	}
    175 	
    176 	return 0;
    177 }
    178 
    179 int process_import_list(yaml_node *parent, yaml_node *child, vita_imports_t *imports) {
    180 	if (!is_scalar(parent)) {
    181 		fprintf(stderr, "error: line: %zd, column: %zd, expecting modules key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent));
    182 		return -1;
    183 	}
    184 	
    185 	yaml_scalar *key = &parent->data.scalar;
    186 	
    187 	vita_imports_lib_t *import = vita_imports_lib_new(key->value,0,0);
    188 	
    189 	if (yaml_iterate_mapping(child, (mapping_functor)process_import, import) < 0)
    190 		return -1;
    191 	
    192 	imports->libs = realloc(imports->libs, (imports->n_libs+1)*sizeof(vita_imports_lib_t*));
    193 	imports->libs[imports->n_libs++] = import;
    194 	return 0;
    195 }
    196 
    197 vita_imports_t *read_vita_imports(yaml_document *doc) {
    198 	if (!is_mapping(doc)) {
    199 		fprintf(stderr, "error: line: %zd, column: %zd, expecting root node to be a mapping, got '%s'.\n", doc->position.line, doc->position.column, node_type_str(doc));
    200 		return NULL;
    201 	}
    202 	
    203 	yaml_mapping *root = &doc->data.mapping;
    204 	
    205 	// check we only have one entry
    206 	if (root->count < 1) {
    207 		fprintf(stderr, "error: line: %zd, column: %zd, expecting at least one entry within root mapping, got %zd.\n", doc->position.line, doc->position.column, root->count);
    208 		return NULL;
    209 	}
    210 	
    211 	vita_imports_t *imports  = vita_imports_new(0);
    212 
    213 	for(int n = 0; n < root->count; n++){
    214 		// check lhs is a scalar
    215 		if (is_scalar(root->pairs[n]->lhs)) {
    216 			const char *root_value = root->pairs[n]->lhs->data.scalar.value;
    217 			if (strcmp(root_value, "firmware") == 0) {
    218 				if (!is_scalar(root->pairs[n]->rhs))
    219 					return NULL;
    220 				const char *firm = root->pairs[n]->rhs->data.scalar.value;
    221 				// skip default firmware
    222 				if (strcmp(firm, "3.60") == 0)
    223 					continue;
    224 				imports->firmware = strdup(firm);
    225 				int i = 0;
    226 				int j = 0;
    227 				imports->postfix[j++] = '_';
    228 				while (firm[i]) {
    229 					const char v = firm[i++];
    230 					if (v == '.')
    231 						continue;
    232 					imports->postfix[j++] = v;
    233 				}
    234 			}
    235 			else if (strcmp(root_value, "modules") == 0) {
    236 				if (yaml_iterate_mapping(root->pairs[n]->rhs, (mapping_functor)process_import_list, imports) < 0)
    237 					return NULL;
    238 			}
    239 			else {
    240 				fprintf(stderr, "warning: line: %zd, column: %zd, unknow tag '%s'.\n", root->pairs[n]->lhs->position.line, root->pairs[n]->lhs->position.column, root->pairs[n]->lhs->data.scalar.value);
    241 			}
    242 		}
    243 	}
    244 	
    245 	return imports;
    246 	
    247 }
    248 
    249 vita_imports_t *vita_imports_load(const char *filename, int verbose)
    250 {
    251 	FILE *fp = fopen(filename, "r");
    252 	if (fp == NULL) {
    253 		fprintf(stderr, "Error: could not open %s\n", filename);
    254 		return NULL;
    255 	}
    256 	vita_imports_t *imports = vita_imports_loads(fp, verbose);
    257 
    258 	fclose(fp);
    259 
    260 	return imports;
    261 }
    262 
    263 vita_imports_t *vita_imports_loads(FILE *text, int verbose){
    264 	uint32_t nid = 0;
    265 	yaml_error error = {0};
    266 	
    267 	yaml_tree *tree = parse_yaml_stream(text, &error);
    268 	
    269 	if (!tree)
    270 	{
    271 		fprintf(stderr, "error: %s\n", error.problem);
    272 		free(error.problem);
    273 		return NULL;
    274 	}
    275 	
    276 	if (tree->count != 1)
    277 	{
    278 		fprintf(stderr, "error: expecting a single yaml document, got: %zd\n", tree->count);
    279 		// TODO: cleanup tree
    280 		return NULL;
    281 	}
    282 	
    283 	return read_vita_imports(tree->docs[0]);
    284 }