Exemple #1
0
static int setup_openiboot() {
	arm_setup();
	mmu_setup();
	tasks_setup();
	setup_devices();

	LeaveCriticalSection();

	clock_set_sdiv(0);

	aes_setup();

	nor_setup();
	images_setup();
	nvram_setup();

	lcd_setup();
	framebuffer_setup();

	audiohw_init();

	camera_setup();

	return 0;
}
Exemple #2
0
static int setup_openiboot() {
	arm_setup();
	mmu_setup();
	tasks_setup();
	setup_devices();

	LeaveCriticalSection();

#ifndef CONFIG_IPHONE_4
	clock_set_sdiv(0);

	aes_setup();

	nor_setup();
	syscfg_setup();
	images_setup();
	nvram_setup();

	lcd_setup();
	framebuffer_setup();

	audiohw_init();
#endif
    isMultitouchLoaded = 0;
	return 0;
}
Exemple #3
0
void images_duplicate_at(Image* image, uint32_t type, int index, int offset) {
	if(image == NULL)
		return;

	uint32_t totalLen = sizeof(Img2Header) + image->padded;
	uint8_t* buffer = (uint8_t*) malloc(totalLen);

	nor_read(buffer, image->offset, totalLen);
	Img2Header* header = (Img2Header*) buffer;
	header->imageType = type;

	if(index >= 0)
		header->index = index;

	calculateDataHash(buffer + sizeof(Img2Header), image->padded, header->dataHash);

	uint32_t checksum = 0;
	crc32(&checksum, buffer, 0x64);
	header->header_checksum = checksum;

	calculateHash(header, header->hash);

	nor_write(buffer, offset, totalLen);

	free(buffer);

	images_release();
	images_setup();
}
Exemple #4
0
void images_write(Image* image, void* data, unsigned int length, int encrypt) {
	bufferPrintf("images_write(%x, %x, %x)\r\n", image, data, length);
	if(image == NULL)
		return;

	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	uint32_t padded = length;
	if((length & 0xF) != 0) {
		padded = (padded & ~0xF) + 0x10;
	}

	if(image->next != NULL && (image->offset + sizeof(Img2Header) + padded) >= image->next->offset) {
		bufferPrintf("**ABORTED** requested length greater than available space.\r\n");
		return;
	}

	uint32_t totalLen = sizeof(Img2Header) + padded;
	uint8_t* writeBuffer = (uint8_t*) malloc(totalLen);

	mtd_read(dev, writeBuffer, image->offset, sizeof(Img2Header));

	memcpy(writeBuffer + sizeof(Img2Header), data, length);

	if(encrypt)
		aes_838_encrypt(writeBuffer + sizeof(Img2Header), padded, NULL);

	Img2Header* header = (Img2Header*) writeBuffer;
	header->dataLen = length;
	header->dataLenPadded = padded;

	calculateDataHash(writeBuffer + sizeof(Img2Header), padded, header->dataHash);

	uint32_t checksum = 0;
	crc32(&checksum, writeBuffer, 0x64);
	header->header_checksum = checksum;

	calculateHash(header, header->hash);

	bufferPrintf("mtd_write(0x%p, %x, %x, %x)\r\n", dev, writeBuffer, image->offset, totalLen);

	mtd_write(dev, writeBuffer, image->offset, totalLen);

	bufferPrintf("mtd_write(0x%p, %x, %x, %x) done\r\n", dev, writeBuffer, image->offset, totalLen);

	free(writeBuffer);

	mtd_finish(dev);

	images_release();
	images_setup();

}
Exemple #5
0
void images_erase(Image* image) {
	if(image == NULL)
		return;

	nor_erase_sector(image->offset);

	images_release();
	images_setup();
}
Exemple #6
0
void platform_init()
{
	arm_setup();
	mmu_setup();
	tasks_setup();

	// Basic prerequisites for everything else
	miu_setup();
	power_setup();

	clock_setup();

	// Need interrupts for everything afterwards
	interrupt_setup();
	
	gpio_setup();

	// For scheduling/sleeping niceties
	timer_setup();
	event_setup();
	wdt_setup();

	// Other devices
//	uart_setup();
	i2c_setup();

//	dma_setup();

	spi_setup();

	LeaveCriticalSection();

	aes_setup();

	nor_setup();
	syscfg_setup();
	images_setup();
	nvram_setup();

//	lcd_setup();
	framebuffer_hook();	// TODO: Remove once LCD implemented
	framebuffer_setup();

//	audiohw_init();

	framebuffer_setdisplaytext(TRUE);


	gpio_register_interrupt(BUTTONS_HOLD_IRQ, BUTTONS_HOLD_IRQTYPE, BUTTONS_HOLD_IRQLEVEL, BUTTONS_HOLD_IRQAUTOFLIP, gpio_test_handler, 0);
	gpio_interrupt_enable(BUTTONS_HOLD_IRQ);
	gpio_register_interrupt(BUTTONS_HOME_IRQ, BUTTONS_HOME_IRQTYPE, BUTTONS_HOME_IRQLEVEL, BUTTONS_HOME_IRQAUTOFLIP, gpio_test_handler, 1);
	gpio_interrupt_enable(BUTTONS_HOME_IRQ);
	gpio_register_interrupt(BUTTONS_VOLUP_IRQ, BUTTONS_VOLUP_IRQTYPE, BUTTONS_VOLUP_IRQLEVEL, BUTTONS_VOLUP_IRQAUTOFLIP, gpio_test_handler, 2);
	gpio_interrupt_enable(BUTTONS_VOLUP_IRQ);
	gpio_register_interrupt(BUTTONS_VOLDOWN_IRQ, BUTTONS_VOLDOWN_IRQTYPE, BUTTONS_VOLDOWN_IRQLEVEL, BUTTONS_VOLDOWN_IRQAUTOFLIP, gpio_test_handler, 3);
	gpio_interrupt_enable(BUTTONS_VOLDOWN_IRQ);
}
Exemple #7
0
static void nor_init()
{
	if(!nor_device_init(&nor_device))
	{
		mtd_register(&nor_device.mtd);

#ifdef S5L8900
		images_setup();
#endif
		nvram_setup();
		syscfg_setup();
	}
}
Exemple #8
0
void images_from_template(Image* image, uint32_t type, int index, void* dataBuffer, unsigned int len, int encrypt) {
	if(image == NULL)
		return;

	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	uint32_t offset = MaxOffset + (SegmentSize - (MaxOffset % SegmentSize));
	uint32_t padded = len;
	if((len & 0xF) != 0) {
		padded = (padded & ~0xF) + 0x10;
	}

	uint32_t totalLen = sizeof(Img2Header) + padded;
	uint8_t* buffer = (uint8_t*) malloc(totalLen);

	mtd_read(dev, buffer, image->offset, sizeof(Img2Header));
	Img2Header* header = (Img2Header*) buffer;
	header->imageType = type;

	if(index >= 0)
		header->index = index;

	header->dataLen = len;
	header->dataLenPadded = padded;

	memcpy(buffer + sizeof(Img2Header), dataBuffer, len);
	if(encrypt)
		aes_838_encrypt(buffer + sizeof(Img2Header), padded, NULL);

	calculateDataHash(buffer + sizeof(Img2Header), image->padded, header->dataHash);

	uint32_t checksum = 0;
	crc32(&checksum, buffer, 0x64);
	header->header_checksum = checksum;

	calculateHash(header, header->hash);

	mtd_write(dev, buffer, offset, totalLen);

	free(buffer);

	mtd_finish(dev);

	images_release();
	images_setup();
}
Exemple #9
0
void images_append(void* data, int len) {
	if(MaxOffset >= 0xfc000 || (MaxOffset + len) >= 0xfc000) {
		bufferPrintf("writing image of size %d at %x would overflow NOR!\r\n", len, MaxOffset);
	} else {
		nor_write(data, MaxOffset, len);

		// Destroy any following image
		if((MaxOffset + len) < 0xfc000) {
			uint8_t zero = 0;
			nor_write(&zero, MaxOffset + len, 1);
		}
		images_release();
		images_setup();
	}
}
Exemple #10
0
void images_duplicate(Image* image, uint32_t type, int index) {
	if(image == NULL)
		return;

	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	uint32_t offset = MaxOffset + (SegmentSize - (MaxOffset % SegmentSize));

	uint32_t totalLen = sizeof(Img2Header) + image->padded;
	uint8_t* buffer = (uint8_t*) malloc(totalLen);

	mtd_read(dev, buffer, image->offset, totalLen);
	Img2Header* header = (Img2Header*) buffer;
	header->imageType = type;

	if(index >= 0)
		header->index = index;

	calculateDataHash(buffer + sizeof(Img2Header), image->padded, header->dataHash);

	uint32_t checksum = 0;
	crc32(&checksum, buffer, 0x64);
	header->header_checksum = checksum;

	calculateHash(header, header->hash);

	mtd_write(dev, buffer, offset, totalLen);

	free(buffer);

	mtd_finish(dev);

	images_release();
	images_setup();
}
Exemple #11
0
void images_append(void* data, int len) {
	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	if(MaxOffset >= 0xfc000 || (MaxOffset + len) >= 0xfc000) {
		bufferPrintf("**ABORTED** Writing image of size %d at %x would overflow NOR!\r\n", len, MaxOffset);
	} else {
		mtd_write(dev, data, MaxOffset, len);

		// Destroy any following image
		if((MaxOffset + len) < 0xfc000) {
			uint8_t zero = 0;
			mtd_write(dev, &zero, MaxOffset + len, 1);
		}

		images_release();
		images_setup();
	}

	mtd_finish(dev);
}
Exemple #12
0
void images_uninstall(uint32_t _fourcc, uint32_t _unreplace) {
	ImageDataList* list = NULL;
	ImageDataList* cur = NULL;
	ImageDataList* oldImage = NULL;

	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	Image* curImage = imageList;

	while(curImage != NULL) {
		if(curImage->type != _fourcc) {
			if(cur == NULL) {
				list = cur = malloc(sizeof(ImageDataList));
			} else {
				cur->next = malloc(sizeof(ImageDataList));
				cur = cur->next;
			}

			bufferPrintf("Reading: ");
			print_fourcc(curImage->type);
			bufferPrintf(" (%d bytes)\r\n", curImage->padded);

			cur->type = curImage->type;
			cur->next = NULL;
			cur->data = malloc(curImage->padded);
			mtd_read(dev, cur->data, curImage->offset, curImage->padded);

			if(_fourcc != _unreplace && cur->type == _unreplace) {
				oldImage = cur;
			}
		} else {
			bufferPrintf("Skipping: ");
			print_fourcc(curImage->type);
			bufferPrintf(" (%d bytes)\r\n", curImage->padded);
		}

		curImage = curImage->next;
	}

	mtd_finish(dev);

	if(_fourcc != _unreplace && oldImage == NULL) {
		bufferPrintf("No openiBoot installation was found.\n");
		while(list != NULL) {
			cur = list;
			list = list->next;
			free(cur->data);
			free(cur);
		}
		return;
	}

	oldImage->type = _fourcc;
	images_change_type(oldImage->data, _fourcc);

	images_rewind();
	while(list != NULL) {
		cur = list;
		list = list->next;
		AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;

		bufferPrintf("Flashing: ");
		print_fourcc(cur->type);
		bufferPrintf(" (%x, %d bytes)\r\n", cur->data, header->base.size);

		images_append(cur->data, header->base.size);

		free(cur->data);
		free(cur);
	}

	bufferPrintf("Images uninstalled.\r\n");

	images_release();
	images_setup();

	bufferPrintf("Uninstall complete.\r\n");
}
Exemple #13
0
void images_install(void* newData, size_t newDataLen, uint32_t newFourcc, uint32_t replaceFourcc) {
	ImageDataList* list = NULL;
	ImageDataList* cur = NULL;
	ImageDataList* toReplace = NULL;
    ImageDataList* verify = NULL;
    
	int isReplace = (replaceFourcc != newFourcc) ? TRUE : FALSE;
	int isUpgrade = FALSE;

	mtd_t *dev = images_device();
	if(!dev)
		return;

	mtd_prepare(dev);

	Image* curImage = imageList;
    
	while(curImage != NULL) {
		if(cur == NULL) {
			list = cur = verify = malloc(sizeof(ImageDataList));
		} else {
			cur->next = malloc(sizeof(ImageDataList));
			cur = cur->next;
		}

		bufferPrintf("Reading: ");
		print_fourcc(curImage->type);
		bufferPrintf(" (%d bytes)\r\n", curImage->padded);

		cur->type = curImage->type;
		cur->next = NULL;
		cur->data = malloc(curImage->padded);
		mtd_read(dev, cur->data, curImage->offset, curImage->padded);

		if(isReplace && cur->type == replaceFourcc) {
			isUpgrade = TRUE;
		} else if(cur->type == newFourcc) {
			toReplace = cur;
		}

		curImage = curImage->next;
	}

	mtd_finish(dev);

	if(!isUpgrade) {
		bufferPrintf("Performing installation... (%d bytes)\r\n", newDataLen);

		ImageDataList* ibox = malloc(sizeof(ImageDataList));
		ibox->type = replaceFourcc;
		ibox->data = toReplace->data;
		ibox->next = toReplace->next;

		toReplace->next = ibox;
		toReplace->data = images_inject_img3(toReplace->data, newData, newDataLen);
		images_change_type(ibox->data, ibox->type);
	} else {
		bufferPrintf("Performing upgrade... (%d bytes)\r\n", newDataLen);
		void* newIBoot = images_inject_img3(toReplace->data, newData, newDataLen);
		free(toReplace->data);
		toReplace->data = newIBoot;
	}

    //check for size and availability
    size_t newPaddedDataLen=0;
    size_t totalBytes=0;
    //if somebody can find how to get padded length for new ibot maybe this loop not needed
    while(verify != NULL) {
        cur = verify;
        verify = verify->next;
        AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;
        totalBytes += header->base.size;
        
        if(cur->type == newFourcc) {
            newPaddedDataLen = header->base.size;
        }
    }
    
    bufferPrintf("Total size to be written %d\r\n",totalBytes);
    if((ImagesStart + totalBytes) >= 0xfc000) {
        bufferPrintf("**ABORTED** Writing total image size: 0x%x, new ibot size: 0x%x at 0x%x would overflow NOR!\r\n", totalBytes, newPaddedDataLen,ImagesStart);
        images_rewind();
        images_release();
        images_setup();
        return;
    }
	
	bufferPrintf("Flashing...\r\n");

	images_rewind();
	while(list != NULL) {
		cur = list;
		list = list->next;
		AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;

		bufferPrintf("Flashing: ");
		print_fourcc(cur->type);
		bufferPrintf(" (%x, %d bytes)\r\n", cur->data, header->base.size);

		images_append(cur->data, header->base.size);

		free(cur->data);
		free(cur);
	}
	bufferPrintf("Flashing Complete, Free space after flashing %d\r\n",0xfc000-MaxOffset);

	images_release();
	images_setup();

    //bufferPrintf("Configuring openiBoot settings...\r\n");

/*#ifndef CONFIG_S5L8720	//TODO: add this back in once FTL is up and running
    Volume* volume;
    io_func* io;

    io = bdev_open(0);
    volume = openVolume(io);

    char buffer [sizeof(XSTRINGIFY(OPENIBOOT_VERSION))];
    strcpy(buffer, XSTRINGIFY(OPENIBOOT_VERSION));
    add_hfs(volume, (uint8_t*)buffer, sizeof(buffer), "/openiboot");

    closeVolume(volume);
    CLOSE(io);

    ftl_sync();
#endif*/ // TODO: This is broken now, move into menu.c for next release -- Ricky26

  /*  if(!nvram_getvar("opib-temp-os")) {
    	nvram_setvar("opib-temp-os", "0");
    }
    
    if(!nvram_getvar("opib-default-os")) {
		nvram_setvar("opib-default-os", "1");
    }

    if(!nvram_getvar("opib-menu-timeout")) {
		nvram_setvar("opib-menu-timeout", "10000");
    }

    nvram_save();*/ // TODO: The defaults should NOT be written to NVRAM. -- Ricky26

    //bufferPrintf("openiBoot installation complete.\r\n");
}
Exemple #14
0
void images_uninstall() {
	ImageDataList* list = NULL;
	ImageDataList* cur = NULL;
	ImageDataList* iboot = NULL;

	Image* curImage = imageList;

	bufferPrintf("Reading images...\r\n");
	while(curImage != NULL) {
		if(curImage->type != fourcc("ibot")) {
			if(cur == NULL) {
				list = cur = malloc(sizeof(ImageDataList));
			} else {
				cur->next = malloc(sizeof(ImageDataList));
				cur = cur->next;
			}

			bufferPrintf("Reading: ");
			print_fourcc(curImage->type);
			bufferPrintf(" (%d bytes)\r\n", curImage->padded);

			cur->type = curImage->type;
			cur->next = NULL;
			cur->data = malloc(curImage->padded);
			nor_read(cur->data, curImage->offset, curImage->padded);

			if(cur->type == fourcc("ibox")) {
				iboot = cur;
			}
		} else {
			bufferPrintf("Skipping: ");
			print_fourcc(curImage->type);
			bufferPrintf(" (%d bytes)\r\n", curImage->padded);
		}

		curImage = curImage->next;
	}

	if(iboot == NULL) {
		bufferPrintf("openiboot does not seem to be installed\n");
		while(list != NULL) {
			cur = list;
			list = list->next;
			free(cur->data);
			free(cur);
		}
		return;
	}

	iboot->type = fourcc("ibot");
	images_change_type(iboot->data, fourcc("ibot"));

	bufferPrintf("Flashing...\r\n");

	images_rewind();
	while(list != NULL) {
		cur = list;
		list = list->next;
		AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;

		bufferPrintf("Flashing: ");
		print_fourcc(cur->type);
		bufferPrintf(" (%x, %d bytes)\r\n", cur->data, header->base.size);

		images_append(cur->data, header->base.size);

		free(cur->data);
		free(cur);
	}

	bufferPrintf("Done with uninstallation!\r\n");

	images_release();
	images_setup();

	bufferPrintf("Refreshed image list\r\n");
}
Exemple #15
0
void images_install(void* newData, size_t newDataLen) {
	ImageDataList* list = NULL;
	ImageDataList* cur = NULL;
	ImageDataList* iboot = NULL;

	int isUpgrade = FALSE;

	Image* curImage = imageList;

	bufferPrintf("Reading images...\r\n");
	while(curImage != NULL) {
		if(cur == NULL) {
			list = cur = malloc(sizeof(ImageDataList));
		} else {
			cur->next = malloc(sizeof(ImageDataList));
			cur = cur->next;
		}

		bufferPrintf("Reading: ");
		print_fourcc(curImage->type);
		bufferPrintf(" (%d bytes)\r\n", curImage->padded);

		cur->type = curImage->type;
		cur->next = NULL;
		cur->data = malloc(curImage->padded);
		nor_read(cur->data, curImage->offset, curImage->padded);

		if(cur->type == fourcc("ibox")) {
			isUpgrade = TRUE;
		} else if(cur->type == fourcc("ibot")) {
			iboot = cur;
		}

		curImage = curImage->next;
	}

	if(!isUpgrade) {
		bufferPrintf("Performing installation... (%d bytes)\r\n", newDataLen);

		ImageDataList* ibox = malloc(sizeof(ImageDataList));
		ibox->type = fourcc("ibox");
		ibox->data = iboot->data;
		ibox->next = iboot->next;

		iboot->next = ibox;
		iboot->data = images_inject_img3(iboot->data, newData, newDataLen);
		images_change_type(ibox->data, ibox->type);
	} else {
		bufferPrintf("Performing upgrade... (%d bytes)\r\n", newDataLen);
		void* newIBoot = images_inject_img3(iboot->data, newData, newDataLen);
		free(iboot->data);
		iboot->data = newIBoot;
	}


	bufferPrintf("Flashing...\r\n");

	images_rewind();
	while(list != NULL) {
		cur = list;
		list = list->next;
		AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;

		bufferPrintf("Flashing: ");
		print_fourcc(cur->type);
		bufferPrintf(" (%x, %d bytes)\r\n", cur->data, header->base.size);

		images_append(cur->data, header->base.size);

		free(cur->data);
		free(cur);
	}

	bufferPrintf("Done with installation!\r\n");

	images_release();
	images_setup();

	bufferPrintf("Refreshed image list\r\n");
}
Exemple #16
0
void images_install(void* newData, size_t newDataLen, uint32_t newFourcc, uint32_t replaceFourcc) {
	ImageDataList* list = NULL;
	ImageDataList* cur = NULL;
	ImageDataList* toReplace = NULL;
    ImageDataList* verify = NULL;
    
	int isReplace = (replaceFourcc != newFourcc) ? TRUE : FALSE;
	int isUpgrade = FALSE;

	Image* curImage = imageList;
    
	while(curImage != NULL) {
		if(cur == NULL) {
			list = cur = verify = malloc(sizeof(ImageDataList));
		} else {
			cur->next = malloc(sizeof(ImageDataList));
			cur = cur->next;
		}

		bufferPrintf("Reading: ");
		print_fourcc(curImage->type);
		bufferPrintf(" (%d bytes)\r\n", curImage->padded);

		cur->type = curImage->type;
		cur->next = NULL;
		cur->data = malloc(curImage->padded);
		nor_read(cur->data, curImage->offset, curImage->padded);

		if(isReplace && cur->type == replaceFourcc) {
			isUpgrade = TRUE;
		} else if(cur->type == newFourcc) {
			toReplace = cur;
		}

		curImage = curImage->next;
	}

	if(!isUpgrade) {
		bufferPrintf("Performing installation... (%d bytes)\r\n", newDataLen);

		ImageDataList* ibox = malloc(sizeof(ImageDataList));
		ibox->type = replaceFourcc;
		ibox->data = toReplace->data;
		ibox->next = toReplace->next;

		toReplace->next = ibox;
		toReplace->data = images_inject_img3(toReplace->data, newData, newDataLen);
		images_change_type(ibox->data, ibox->type);
	} else {
		bufferPrintf("Performing upgrade... (%d bytes)\r\n", newDataLen);
		void* newIBoot = images_inject_img3(toReplace->data, newData, newDataLen);
		free(toReplace->data);
		toReplace->data = newIBoot;
	}

    //check for size and availability
    size_t newPaddedDataLen=0;
    size_t totalBytes=0;
    //if somebody can find how to get padded length for new ibot maybe this loop not needed
    while(verify != NULL) {
        cur = verify;
        verify = verify->next;
        AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;
        totalBytes += header->base.size;
        
        if(cur->type == newFourcc) {
            newPaddedDataLen = header->base.size;
        }
    }
    
    bufferPrintf("Total size to be written %d\r\n",totalBytes);
    if((ImagesStart + totalBytes) >= 0xfc000) {
        bufferPrintf("**ABORTED** Writing total image size: 0x%x, new ibot size: 0x%x at 0x%x would overflow NOR!\r\n", totalBytes, newPaddedDataLen,ImagesStart);
        images_rewind();
        images_release();
        images_setup();
        return;
    }
    
	bufferPrintf("Flashing...\r\n");

	images_rewind();
	while(list != NULL) {
		cur = list;
		list = list->next;
		AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;

		bufferPrintf("Flashing: ");
		print_fourcc(cur->type);
		bufferPrintf(" (%x, %d bytes)\r\n", cur->data, header->base.size);

		images_append(cur->data, header->base.size);

		free(cur->data);
		free(cur);
	}
	bufferPrintf("Flashing Complete, Free space after flashing %d\r\n",0xfc000-MaxOffset);

	images_release();
	images_setup();

    bufferPrintf("Configuring openiBoot settings...\r\n");
    nvram_setvar("opib-version", "0.1.2");
    
	if(!nvram_getvar("opib-temp-os")) {
    	nvram_setvar("opib-temp-os", "0");
    }
    
	if(!nvram_getvar("opib-default-os")) {
		nvram_setvar("opib-default-os", "0");
    }

    if(!nvram_getvar("opib-menu-timeout")) {
		nvram_setvar("opib-menu-timeout", "10000");
    }

    nvram_save();
    bufferPrintf("openiBoot installation complete.\r\n");
}