Example #1
0
bool emu_start() {
    bool ret = false;
    long lSize;

    asic_init();

    if (rom_image == NULL) {
        gui_console_printf("No ROM image specified.");
    }
    else {
        FILE *rom = fopen_utf8(rom_image, "rb");
        do {
            if (rom) {
                uint16_t field_type;
                const uint8_t *outer;
                const uint8_t *current;
                const uint8_t *data;
                uint32_t outer_field_size;
                uint32_t data_field_size;
                ti_device_type device_type;
                uint32_t offset;

                // Get ROM file size
                if (fseek(rom, 0L, SEEK_END) < 0) {
                    break;
                }

                lSize = ftell(rom);
                if (lSize < 0) {
                    break;
                }

                if (fseek(rom, 0L, SEEK_SET) < 0) {
                    break;
                }

                // Read whole ROM.
                if (fread(asic.mem->flash.block, 1, lSize, rom) < (size_t)lSize) {
                    break;
                }

                // Parse certificate fields to determine model.
                //device_type = (ti_device_type)(asic.mem->flash.block[0x20017]);
                // We've heard of the OS base being at 0x30000 on at least one calculator.
                for (offset = 0x20000U; offset < 0x40000U; offset += 0x10000U) {
                    outer = asic.mem->flash.block;
                    // Outer 0x800(0) field.
                    if (cert_field_get(outer + offset, asic.mem->flash.size - offset, &field_type, &outer, &outer_field_size)) {
                        break;
                    }
                    if (field_type != 0x800F /*|| field_type == 0x800D || field_type == 0x800E*/) {
                        continue;
                    }
                    //fprintf(stderr, "outer: %p\t%04X\t%p\t%u\n", asic.mem->flash.block, field_type, outer, outer_field_size);

                    // Inner 0x801(0) field: calculator model
                    if (cert_field_get(outer, outer_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 1: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x8012 || data[0] != 0x13) {
                        break;
                    }

                    // Inner 0x802(0) field: skip.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = outer;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    current = data;
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 2: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x8021) {
                        break;
                    }

                    // Inner 0x803(0) field: skip.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = current;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    current = data;
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 3: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x8032) {
                        break;
                    }

                    // Inner 0x80A(0) field: skip.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = current;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    current = data;
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 4: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x80A1) {
                        break;
                    }

                    // Inner 0x80C(0) field: keep.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = current;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    current = data;
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 5: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x80C2) {
                        break;
                    }

                    //fprintf(stderr, "Found calculator type %02X\n", data[1]);
                    if (data[1] != 0 && data[1] != 1) {
                        break;
                    }
                    device_type = (ti_device_type)(data[1]);

                    // If we come here, we've found something.
                    ret = true;
                    break;
                }


                if (ret) {
                    control.device_type = device_type;
                    asic.device_type = device_type;
                }

            }
        } while(0);

        if (!ret) {
            gui_console_printf("Error opening ROM image.\n", rom_image);
            emu_cleanup();
        }

        if (rom) {
            fclose(rom);
        }
    }

    return ret;
}
Example #2
0
bool emu_start(const char *romImage, const char *savedImage) {
    bool ret = false;
    long lSize;
    FILE *imageFile = NULL;

    gui_set_busy(true);

    do {
        if(savedImage != NULL) {
            emu_image_t *image;
            imageFile = fopen_utf8(savedImage, "rb");

            if (!imageFile) {
                break;
            }
            if (fseek(imageFile, 0L, SEEK_END) < 0) {
                break;
            }
            lSize = ftell(imageFile);
            if (lSize < 0) {
                break;
            }
            if (fseek(imageFile, 0L, SEEK_SET) < 0) {
                break;
            }
            if((size_t)lSize < sizeof(emu_image_t)) {
                break;
            }

            image = (emu_image_t*)malloc(lSize);
            if(!image) {
                break;
            }
            if(fread(image, lSize, 1, imageFile) != 1) {
                free(image);
                break;
            }

            sched_reset();
            sched.items[SCHED_THROTTLE].clock = CLOCK_27M;
            sched.items[SCHED_THROTTLE].proc = throttle_interval_event;

            asic_init();
            asic_reset();

            if(image->version != imageVersion || !asic_restore(image)) {
                emu_cleanup();
                free(image);
                break;
            }
            free(image);
            ret = true;
        } else {
            asic_init();
            if (romImage == NULL) {
                gui_console_printf("[CEmu] No ROM image specified.\n");
                break;
            } else {
                FILE *romFile = fopen_utf8(romImage, "rb");
                do {
                    if (romFile) {
                        uint16_t field_type;
                        const uint8_t *outer;
                        const uint8_t *current;
                        const uint8_t *data;
                        uint32_t outer_field_size;
                        uint32_t data_field_size;
                        ti_device_t device_type;
                        uint32_t offset;

                        /* Get ROM file size */
                        if (fseek(romFile, 0L, SEEK_END) < 0) {
                            break;
                        }
                        lSize = ftell(romFile);
                        if (lSize < 0) {
                            break;
                        }
                        if (fseek(romFile, 0L, SEEK_SET) < 0) {
                            break;
                        }

                        /* Read whole ROM. */
                        if (fread(mem.flash.block, 1, lSize, romFile) < (size_t)lSize) {
                            break;
                        }

                        if (mem.flash.block[0x7E] == 0xFE) {
                            break;
                        }

                        /* Parse certificate fields to determine model.                            */
                        /* device_type = (ti_device_type)(asic.mem->flash.block[0x20017]);         */
                        /* We've heard of the OS base being at 0x30000 on at least one calculator. */
                        for (offset = 0x20000U; offset < 0x40000U; offset += 0x10000U) {
                            outer = mem.flash.block;
                            /* Outer 0x800(0) field. */
                            if (cert_field_get(outer + offset, mem.flash.size - offset, &field_type, &outer, &outer_field_size)) {
                                break;
                            }
                            if (field_type != 0x800F /*|| field_type == 0x800D || field_type == 0x800E*/) {
                                continue;
                            }
                            /*fprintf(stderr, "outer: %p\t%04X\t%p\t%u\n", asic.mem->flash.block, field_type, outer, outer_field_size);*/

                            /* Inner 0x801(0) field: calculator model */
                            if (cert_field_get(outer, outer_field_size, &field_type, &data, &data_field_size)) {
                                break;
                            }
                            /*fprintf(stderr, "inner 1: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (field_type != 0x8012 || data[0] != 0x13) {
                                break;
                            }

                            /* Inner 0x802(0) field: skip. */
                            data_field_size = outer_field_size - (data + data_field_size - outer);
                            data = outer;
                            if (cert_field_next(&data, &data_field_size)) {
                                break;
                            }
                            /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            current = data;
                            if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                                break;
                            }
                            /*fprintf(stderr, "inner 2: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (field_type != 0x8021) {
                                break;
                            }

                            /* Inner 0x803(0) field: skip. */
                            data_field_size = outer_field_size - (data + data_field_size - outer);
                            data = current;
                            if (cert_field_next(&data, &data_field_size)) {
                                break;
                            }
                            current = data;
                            /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                                break;
                            }
                            /*fprintf(stderr, "inner 3: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (field_type != 0x8032) {
                                break;
                            }

                            /* Inner 0x80A(0) field: skip. */
                            data_field_size = outer_field_size - (data + data_field_size - outer);
                            data = current;
                            if (cert_field_next(&data, &data_field_size)) {
                                break;
                            }
                            current = data;
                            /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                                break;
                            }
                            /*fprintf(stderr, "inner 4: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (field_type != 0x80A1) {
                                break;
                            }

                            /* Inner 0x80C(0) field: keep. */
                            data_field_size = outer_field_size - (data + data_field_size - outer);
                            data = current;
                            if (cert_field_next(&data, &data_field_size)) {
                                break;
                            }
                            current = data;
                            /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                                break;
                            }
                            /*fprintf(stderr, "inner 5: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/
                            if (field_type != 0x80C2) {
                                break;
                            }

                            /*fprintf(stderr, "Found calculator type %02X\n", data[1]);*/
                            if (data[1] != 0 && data[1] != 1) {
                                break;
                            }
                            device_type = (ti_device_t)(data[1]);

                            /* If we come here, we've found something. */
                            ret = true;
                            break;
                        }

                        if (ret) {
                            set_device_type(device_type);
                        }
                    }
                } while(0);

                if (romFile) {
                    fclose(romFile);
                }
            }
        }
    } while(0);

    if (imageFile) {
        fclose(imageFile);
    }

    if (!ret) {
        gui_console_printf("[CEmu] Error opening image (Corrupted certificate?)\n");
        emu_cleanup();
    }

    gui_set_busy(false);

    return ret;
}