X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fspl%2Fspl_ymodem.c;h=284512478f1be52cf9119b18cf2fe0f73ed64043;hb=HEAD;hp=35f8f80013a8b02821c22bd95eb1cd32c0d45aae;hpb=e8f80a5a58c9b506453cc0780687e8ed457d30a6;p=oweals%2Fu-boot.git diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 35f8f80013..284512478f 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -9,10 +9,12 @@ * Matt Porter */ #include +#include +#include +#include #include #include #include -#include #include #define BUF_SIZE 1024 @@ -37,27 +39,32 @@ static int getcymodem(void) { static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, ulong size, void *addr) { - int res, err; + int res, err, buf_offset; struct ymodem_fit_info *info = load->priv; char *buf = info->buf; while (info->image_read < offset) { res = xyzModem_stream_read(buf, BUF_SIZE, &err); if (res <= 0) - return res; + break; + info->image_read += res; } if (info->image_read > offset) { res = info->image_read - offset; - memcpy(addr, &buf[BUF_SIZE - res], res); + if (info->image_read % BUF_SIZE) + buf_offset = (info->image_read % BUF_SIZE); + else + buf_offset = BUF_SIZE; + memcpy(addr, &buf[buf_offset - res], res); addr = addr + res; } while (info->image_read < offset + size) { res = xyzModem_stream_read(buf, BUF_SIZE, &err); if (res <= 0) - return res; + break; memcpy(addr, buf, res); info->image_read += res; @@ -67,15 +74,16 @@ static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, return size; } -static int spl_ymodem_load_image(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev) +int spl_ymodem_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) { - int size = 0; + ulong size = 0; int err; int res; int ret; connection_info_t info; char buf[BUF_SIZE]; + struct image_header *ih = NULL; ulong addr = 0; info.mode = xyzModem_ymodem; @@ -89,7 +97,25 @@ static int spl_ymodem_load_image(struct spl_image_info *spl_image, if (res <= 0) goto end_stream; - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && + image_get_magic((struct image_header *)buf) == FDT_MAGIC) { + addr = CONFIG_SYS_LOAD_ADDR; + ih = (struct image_header *)addr; + + memcpy((void *)addr, buf, res); + size += res; + addr += res; + + while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) { + memcpy((void *)addr, buf, res); + size += res; + addr += res; + } + + ret = spl_parse_image_header(spl_image, ih); + if (ret) + return ret; + } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic((struct image_header *)buf) == FDT_MAGIC) { struct spl_load_info load; struct ymodem_fit_info info; @@ -108,12 +134,18 @@ static int spl_ymodem_load_image(struct spl_image_info *spl_image, while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) size += res; } else { - ret = spl_parse_image_header(spl_image, - (struct image_header *)buf); + ih = (struct image_header *)buf; + ret = spl_parse_image_header(spl_image, ih); if (ret) - return ret; - addr = spl_image->load_addr; + goto end_stream; +#ifdef CONFIG_SPL_GZIP + if (ih->ih_comp == IH_COMP_GZIP) + addr = CONFIG_SYS_LOAD_ADDR; + else +#endif + addr = spl_image->load_addr; memcpy((void *)addr, buf, res); + ih = (struct image_header *)addr; size += res; addr += res; @@ -128,7 +160,22 @@ end_stream: xyzModem_stream_close(&err); xyzModem_stream_terminate(false, &getcymodem); - printf("Loaded %d bytes\n", size); - return 0; + printf("Loaded %lu bytes\n", size); + +#ifdef CONFIG_SPL_GZIP + if (!(IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic((struct image_header *)buf) == FDT_MAGIC) && + (ih->ih_comp == IH_COMP_GZIP)) { + if (gunzip((void *)(spl_image->load_addr + sizeof(*ih)), + CONFIG_SYS_BOOTM_LEN, + (void *)(CONFIG_SYS_LOAD_ADDR + sizeof(*ih)), + &size)) { + puts("Uncompressing error\n"); + return -EIO; + } + } +#endif + + return ret; } SPL_LOAD_IMAGE_METHOD("UART", 0, BOOT_DEVICE_UART, spl_ymodem_load_image);