/* * LZMA Compressed Kernel Loader * (c) 2009 Philippe Vachon * * Licensed under the GNU General Public License v.2. * See COPYING in the root directory of this source distribution for more * details. */ #include #include #include #include /* LZMA SDK */ #include struct private_data { ILzmaInCallback callback; uint8_t *buffer; struct file *fp; uint32_t total_read; uint32_t last; }; int read_data(void *object, const uint8_t **buffer, uint32_t *size) { struct private_data *pvt = (struct private_data *)object; if (cilo_tell(pvt->fp) > pvt->fp->file_len) { printf("FATAL: Attempt to read past end of file. Aborting.\n"); return LZMA_RESULT_DATA_ERROR; } *size = pvt->fp->file_len - cilo_tell(pvt->fp); *size = *size > 512 ? 512 : *size; pvt->total_read += *size; uint32_t done = (pvt->total_read * 100)/pvt->fp->file_len; if (done % 10 == 0 && done != pvt->last) { printf("%d", done); pvt->last = done; } else if (done != pvt->last && done % 2 == 0) { printf("."); pvt->last = done; } cilo_read(pvt->buffer, *size, 1, pvt->fp); *buffer = pvt->buffer; return LZMA_RESULT_OK; } void load_lzma(struct file *fp, uint32_t load_address, char *cmd_line) { CLzmaDecoderState state; uint8_t buffer[512]; struct private_data pvt; uint8_t props[LZMA_PROPERTIES_SIZE]; uint32_t out_size = 0; uint8_t out_size_read[4]; /* seek to beginning of file */ cilo_seek(fp, 0, SEEK_SET); /* Setup LZMA decoding properties */ cilo_read(props, LZMA_PROPERTIES_SIZE, 1, fp); if (LzmaDecodeProperties(&state.Properties, props, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) { printf("Error while decoding LZMA properties. Aborting.\n"); return; } /* read in out size */ cilo_read(out_size_read, 1, 4, fp); out_size = out_size_read[0] | out_size_read[1] << 8 | out_size_read[2] << 16 | out_size_read[3] << 24; cilo_seek(fp, 4, SEEK_CUR); uint16_t probs[LzmaGetNumProbs(&state.Properties)]; /* setup structs */ pvt.callback.Read = read_data; pvt.buffer = buffer; pvt.fp = fp; pvt.total_read = 0; state.Probs = probs; pvt.last = 100; /* do the decoding */ uint32_t out_processed = 0; int result = LzmaDecode(&state, (ILzmaInCallback *)&pvt, (uint8_t *)load_address, out_size, &out_processed); if (result != LZMA_RESULT_OK) { printf("\nError in decoding LZMA-compressed kernel image. Aborting.\n"); return; } /* kick into kernel: */ printf("100\nStarting kernel at 0x%016x.\n\n", load_address); ((void (*)(uint32_t mem_sz, char *cmd_line))(load_address)) (c_memsz(), cmd_line); }