/* * Parses EEPROM text file and createds binary .eep file * Usage: eepmake input_file output_file */ #include #include #include #include #include #include #include #include "eeptypes.h" #define HEADER_SIGN 0x69502d52 //"R-Pi" in ASCII reversed for endianness //todo: larger initial mallocs struct header_t header; struct atom_t *custom_atom, vinf_atom, gpio_atom, dt_atom; struct vendor_info_d* vinf; struct gpio_map_d* gpiomap; bool product_serial_set, product_id_set, product_ver_set, vendor_set, product_set, gpio_drive_set, gpio_slew_set, gpio_hysteresis_set, gpio_power_set; bool data_receive, has_dt, receive_dt; char **data; char *current_atom; //rearranged to write out unsigned int data_len, custom_ct, total_size, data_cap, custom_cap; int write_binary(char* out) { FILE *fp; int i, offset; short crc; fp=fopen(out, "wb"); if (!fp) { printf("Error writing file %s\n", out); return -1; } fwrite(&header, sizeof(header), 1, fp); current_atom = (char *) malloc(vinf_atom.dlen+ATOM_SIZE-CRC_SIZE); offset = 0; //vendor information atom first part memcpy(current_atom, &vinf_atom, ATOM_SIZE-CRC_SIZE); offset += ATOM_SIZE-2; //data first part memcpy(current_atom+offset, vinf_atom.data, VENDOR_SIZE); offset += VENDOR_SIZE; //data strings memcpy(current_atom+offset, vinf->vstr, vinf->vslen); offset += vinf->vslen; memcpy(current_atom+offset, vinf->pstr, vinf->pslen); offset += vinf->pslen; //vinf last part crc = getcrc(current_atom, offset); memcpy(current_atom+offset, &crc, CRC_SIZE); offset += CRC_SIZE; fwrite(current_atom, offset, 1, fp); free(current_atom); current_atom = (char *) malloc(gpio_atom.dlen+ATOM_SIZE-CRC_SIZE); offset = 0; //GPIO map first part memcpy(current_atom, &gpio_atom, ATOM_SIZE-CRC_SIZE); offset += ATOM_SIZE-CRC_SIZE; //GPIO data memcpy(current_atom+offset, gpiomap, GPIO_SIZE); offset += GPIO_SIZE; //GPIO map last part crc = getcrc(current_atom, offset); memcpy(current_atom+offset, &crc, CRC_SIZE); offset += CRC_SIZE; fwrite(current_atom, offset, 1, fp); free(current_atom); if (has_dt) { printf("Writing out DT...\n"); current_atom = (char *) malloc(dt_atom.dlen+ATOM_SIZE-CRC_SIZE); offset = 0; memcpy(current_atom, &dt_atom, ATOM_SIZE-CRC_SIZE); offset += ATOM_SIZE-CRC_SIZE; memcpy(current_atom+offset, dt_atom.data, dt_atom.dlen-CRC_SIZE); offset += dt_atom.dlen-CRC_SIZE; crc = getcrc(current_atom, offset); memcpy(current_atom+offset, &crc, CRC_SIZE); offset += CRC_SIZE; fwrite(current_atom, offset, 1, fp); free(current_atom); } for (i = 0; iserial_4, &high1, &vinf->serial_3, &high2, &vinf->serial_2, &vinf->serial_1); vinf->serial_3 |= high1<<16; vinf->serial_2 |= high2<<16; if ((vinf->serial_4==0) && (vinf->serial_3==0) && (vinf->serial_2==0) && (vinf->serial_1==0)) { //read 128 random bits from /dev/urandom int random_file = open("/dev/urandom", O_RDONLY); ssize_t result = read(random_file, &vinf->serial_1, 16); close(random_file); if (result <= 0) printf("Unable to read from /dev/urandom to set up UUID"); else { //put in the version vinf->serial_3 = (vinf->serial_3 & 0xffff0fff) | 0x00004000; //put in the variant vinf->serial_2 = (vinf->serial_2 & 0x3fffffff) | 0x80000000; printf("UUID=%08x-%04x-%04x-%04x-%04x%08x\n", vinf->serial_4, vinf->serial_3>>16, vinf->serial_3 & 0xffff, vinf->serial_2>>16, vinf->serial_2 & 0xffff, vinf->serial_1); } } } else if (strcmp(cmd, "product_id")==0) { product_id_set = true; //required field sscanf(c, "%100s %hx", cmd, &vinf->pid); } else if (strcmp(cmd, "product_ver")==0) { product_ver_set = true; //required field sscanf(c, "%100s %hx", cmd, &vinf->pver); } else if (strcmp(cmd, "vendor")==0) { vendor_set = true; //required field vinf->vstr = (char*) malloc (256); sscanf(c, "%100s \"%255[^\"]\"", cmd, vinf->vstr); total_size-=vinf->vslen; vinf_atom.dlen-=vinf->vslen; vinf->vslen = strlen(vinf->vstr); total_size+=vinf->vslen; vinf_atom.dlen+=vinf->vslen; } else if (strcmp(cmd, "product")==0) { product_set = true; //required field vinf->pstr = (char*) malloc (256); sscanf(c, "%100s \"%255[^\"]\"", cmd, vinf->pstr); total_size-=vinf->pslen; vinf_atom.dlen-=vinf->pslen; vinf->pslen = strlen(vinf->pstr); total_size+=vinf->pslen; vinf_atom.dlen+=vinf->pslen; } /* GPIO map related part */ else if (strcmp(cmd, "gpio_drive")==0) { gpio_drive_set = true; //required field sscanf(c, "%100s %1x", cmd, &val); if (val>8 || val<0) printf("Warning: gpio_drive property in invalid region, using default value instead\n"); else gpiomap->flags |= val; } else if (strcmp(cmd, "gpio_slew")==0) { gpio_slew_set = true; //required field sscanf(c, "%100s %1x", cmd, &val); if (val>2 || val<0) printf("Warning: gpio_slew property in invalid region, using default value instead\n"); else gpiomap->flags |= val<<4; } else if (strcmp(cmd, "gpio_hysteresis")==0) { gpio_hysteresis_set = true; //required field sscanf(c, "%100s %1x", cmd, &val); if (val>2 || val<0) printf("Warning: gpio_hysteresis property in invalid region, using default value instead\n"); else gpiomap->flags |= val<<6; } else if (strcmp(cmd, "back_power")==0) { gpio_power_set = true; //required field sscanf(c, "%100s %1x", cmd, &val); if (val>2 || val<0) printf("Warning: back_power property in invalid region, using default value instead\n"); else gpiomap->power = val; } else if (strcmp(cmd, "setgpio")==0) { fn = (char*) malloc (101); pull = (char*) malloc (101); sscanf(c, "%100s %d %100s %100s", cmd, &val, fn, pull); if (val=GPIO_COUNT) printf("Error: GPIO number out of bounds\n"); else { valid = true; pin = 0; if (strcmp(fn, "INPUT")==0) { //no action } else if (strcmp(fn, "OUTPUT")==0) { pin |= 1; } else if (strcmp(fn, "ALT0")==0) { pin |= 4; } else if (strcmp(fn, "ALT1")==0) { pin |= 5; } else if (strcmp(fn, "ALT2")==0) { pin |= 6; } else if (strcmp(fn, "ALT3")==0) { pin |= 7; } else if (strcmp(fn, "ALT4")==0) { pin |= 3; } else if (strcmp(fn, "ALT5")==0) { pin |= 2; } else { printf("Error at setgpio: function type not recognised\n"); valid=false; } if (strcmp(pull, "DEFAULT")==0) { //no action } else if (strcmp(pull, "UP")==0) { pin |= 1<<5; } else if (strcmp(pull, "DOWN")==0) { pin |= 2<<5; } else if (strcmp(pull, "NONE")==0) { pin |= 3<<5; } else { printf("Error at setgpio: pull type not recognised\n"); valid=false; } pin |= 1<<7; //board uses this pin if (valid) gpiomap->pins[val] = pin; } } /* DT atom related part */ else if (strcmp(cmd, "dt_blob")==0) { finish_data(); has_dt = true; c+=strlen("dt_blob"); receive_dt=true; data_receive=true; data_len = 0; data_cap = 4; data = &dt_atom.data; *data = (char *) malloc(data_cap); parse_data(c); continue_data = true; } /* Custom data related part */ else if (strcmp(cmd, "custom_data")==0) { finish_data(); c+=strlen("custom_data"); if (custom_cap == custom_ct) { custom_cap *= 2; custom_atom = (struct atom_t*) realloc(custom_atom, custom_cap * sizeof(struct atom_t)); } receive_dt=false; data_receive=true; data_len = 0; data_cap = 4; data = &custom_atom[custom_ct].data; *data = (char *) malloc(data_cap); parse_data(c); continue_data = true; } else if (strcmp(cmd, "end") ==0) { //close last data atom continue_data=false; } /* Incoming data */ else if (data_receive) { parse_data(c); continue_data = true; } if (!continue_data) finish_data(); } int read_text(char* in) { FILE * fp; char * line = NULL; char * c = NULL; size_t len = 0; ssize_t read; char *comment = NULL; int atomct = 2; int linect = 0; char * command = (char*) malloc (101); int i; has_dt = false; printf("Opening file %s for read\n", in); fp = fopen(in, "r"); if (fp == NULL) { printf("Error opening input file\n"); return -1; } //allocating memory and setting up required atoms custom_cap = 1; custom_atom = (struct atom_t*) malloc(sizeof(struct atom_t) * custom_cap); total_size=ATOM_SIZE*2+HEADER_SIZE+VENDOR_SIZE+GPIO_SIZE; vinf_atom.type = ATOM_VENDOR_TYPE; vinf_atom.count = ATOM_VENDOR_NUM; vinf = (struct vendor_info_d *) calloc(1, sizeof(struct vendor_info_d)); vinf_atom.data = (char *)vinf; vinf_atom.dlen = VENDOR_SIZE + CRC_SIZE; gpio_atom.type = ATOM_GPIO_TYPE; gpio_atom.count = ATOM_GPIO_NUM; gpiomap = (struct gpio_map_d *) calloc(1, sizeof(struct gpio_map_d)); gpio_atom.data = (char *)gpiomap; gpio_atom.dlen = GPIO_SIZE + CRC_SIZE; while ((read = getline(&line, &len, fp)) != -1) { linect++; c = line; for (i=0; i3) { if (strcmp(argv[3], "-c")==0) { custom_o=4; } else { //DT file specified if (dt_atom.dlen) total_size-=(ATOM_SIZE +dt_atom.dlen - CRC_SIZE); ret = read_dt(argv[3]); if (ret) { printf("Error reading DT file, aborting\n"); return 0; } } } if (argc>4 && strcmp(argv[4], "-c")==0) custom_o = 5; if (custom_o) for (i = custom_o; i