/******************************************************************************
*
* bootLoadModuleInflate
*	by Curt McDowell, Broadcom Corp. 08/27/99
*
* Like bootLoadModuleInflate, except passes the data through inflate() first.
* This is a pain in the neck and a memory hog because bootLoadModule wants
* a file descriptor.  We use a hack described on the VxWorks support
* groups, which is to create a memDev on the decompressed data buffer,
* open it as a file, and pass that fd to bootLoadModule.
*
* TODO: don't call memDrv() if already initialized
* 	delete mem: drive after load is complete
*	These things may cause multiple calls to this routine to fail.
*
* RETURNS: OK or ERROR
*/

#define DECOMP_BUF_SIZE		(RAM_HIGH_ADRS - RAM_LOW_ADRS)
#define COMP_BUF_SIZE		(DECOMP_BUF_SIZE / 3)

STATUS bootLoadModuleInflate(int zfd, FUNCPTR *pEntry)
{
    char		*imageBuf = NULL;
    char		*compBuf = NULL;
    int			fd = -1;
    int			rv = ERROR;
    int			compSize, r;
    extern STATUS	inflate(char *src, char *dst, int src_size);

    if ((compBuf = malloc(COMP_BUF_SIZE)) == NULL) {
	printErr("Not enough memory for image buffer\n");
	goto done;
    }

    compSize = 0;

    while ((r = read(zfd,	/* Read loop required to support network */
		     compBuf + compSize,
		     COMP_BUF_SIZE - compSize)) > 0)
	compSize += r;

    if (r < 0) {
	printErr("Read failed: errno = %d\n", errnoGet());
	goto done;
    }

    if (compSize == COMP_BUF_SIZE) {
	printErr("Compressed image too large\n");
	goto done;
    }

    printErr("Uncompressing %d bytes... ", compSize);

    if ((imageBuf = malloc(DECOMP_BUF_SIZE)) == NULL) {
	printErr("Not enough memory for decompression buffer\n");
	goto done;
    }

    if ((r = inflate(compBuf, imageBuf, compSize)) < 0) {
	printErr("\nUncompress failed\n");
	goto done;
    }

    printErr("\nLoading image... ");

    memDrv();
    memDevCreate("mem:", imageBuf, DECOMP_BUF_SIZE);

    if ((fd = open("mem:0", O_RDONLY, 0)) < 0) {
	printErr("\nCannot open memory device.\n");
	goto done;
    }

    if (bootLoadModule(fd, pEntry) != OK) {
	printErr("\nError loading: errno = %d\n", errnoGet());
	goto done;
    }

    printErr("\n");

    rv = OK;

 done:
    if (fd >= 0)
	close(fd);
    if (imageBuf)
	free(imageBuf);
    if (compBuf)
	free(compBuf);

    return rv;
}


