#include #include #include #include #include #include #include #include "rk27load.h" #include "common.h" #include "scramble.h" #include "checksum.h" #include "stage1_upload.h" /* ### upload sdram init code ### */ int upload_stage1_code(libusb_device_handle *hdev, char *fn_stage1, bool do_scramble) { FILE *f; int ret; uint8_t *code; uint32_t codesize; uint16_t cks; if ((f = fopen(fn_stage1, "rb")) == NULL) { fprintf(stderr, "[error]: Could not open file \"%s\"\n", fn_stage1); return -10; } codesize = filesize(f); if (codesize > 0x1fe) { fprintf(stderr, "[error]: Code too big for stage1\n"); return -11; } fprintf(stderr, "[stage1]: Loading %d bytes (%s) of code... ", codesize, fn_stage1); code = (uint8_t *)malloc(0x200); if (code == NULL) { fprintf(stderr, "\n[error]: Out of memory\n"); fclose(f); return -12; } memset(code, 0, 0x200); if (fread(code, 1, codesize, f) != codesize) { fprintf(stderr, "\n[error]: I/O error\n"); fclose(f); free(code); return -13; } fprintf(stderr, "done\n"); fclose(f); /* encode data if requested */ if (do_scramble) { fprintf(stderr, "[stage1]: Encoding %d bytes of data ... ", codesize); scramble(code, code, codesize); fprintf(stderr, "done\n"); } fprintf(stderr, "[stage1]: codesize = %d (0x%x)\n", codesize, codesize); fprintf(stderr, "[stage1]: Calculating checksum... "); cks = checksum((void *)code, codesize); fprintf(stderr, "0x%04x\n", cks); code[0x1fe] = (cks >> 8) & 0xff; code[0x1ff] = cks & 0xff; codesize += 2; fprintf(stderr, "[stage1]: Uploading code (%d bytes)... ", codesize); ret = libusb_control_transfer(hdev, /* device handle */ USB_EP0, /* bmRequestType */ VCMD_UPLOAD, /* bRequest */ 0, /* wValue */ VCMD_INDEX_STAGE1, /* wIndex */ code, /* data */ codesize, /* wLength */ USB_TIMEOUT /* timeout */ ); if (ret < 0) { fprintf(stderr, "\n[error]: Code upload request failed (ret=%d)\n", ret); free(code); return -14; } if (ret != (int)codesize) { fprintf(stderr, "\n[error]: Sent %d of %d total\n", ret, codesize); free(code); return -15; } sleep(1); /* wait for code to finish */ fprintf(stderr, "done\n"); /* free code */ free(code); return 0; }