rockbox/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c
Aidan MacDonald 15ad1c42db X1000: simplify NAND driver
- Removed unnecessary layers of generic code
- Software ECC is gone since we don't need it now (and maybe not ever)
- Removed bounce buffering, so callers must now align buffers

Change-Id: I33fbac9d9d12a4657980b8618c7d62bfa91e2ea0
2021-05-06 08:37:26 +01:00

210 lines
5.4 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2021 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "installer.h"
#include "nand-x1000.h"
#include "system.h"
#include "core_alloc.h"
#include "file.h"
#define INSTALL_SUCCESS 0
#define ERR_FLASH_OPEN_FAILED (-1)
#define ERR_FLASH_ENABLE_WP_FAILED (-2)
#define ERR_FLASH_DISABLE_WP_FAILED (-3)
#define ERR_FLASH_ERASE_FAILED (-4)
#define ERR_FLASH_WRITE_FAILED (-5)
#define ERR_FLASH_READ_FAILED (-6)
#define ERR_OUT_OF_MEMORY (-7)
#define ERR_CANNOT_READ_FILE (-8)
#define ERR_CANNOT_WRITE_FILE (-9)
#define ERR_WRONG_SIZE (-10)
#define BOOT_IMAGE_SIZE (128 * 1024)
static int install_from_buffer(const void* buf)
{
int status = INSTALL_SUCCESS;
int mf_id, dev_id;
if(nand_open())
return ERR_FLASH_OPEN_FAILED;
if(nand_identify(&mf_id, &dev_id)) {
status = ERR_FLASH_OPEN_FAILED;
goto _exit;
}
if(nand_enable_writes(true)) {
status = ERR_FLASH_DISABLE_WP_FAILED;
goto _exit;
}
if(nand_erase(0, BOOT_IMAGE_SIZE)) {
status = ERR_FLASH_ERASE_FAILED;
goto _exit;
}
if(nand_write(0, BOOT_IMAGE_SIZE, (const uint8_t*)buf)) {
status = ERR_FLASH_WRITE_FAILED;
goto _exit;
}
if(nand_enable_writes(false)) {
status = ERR_FLASH_ENABLE_WP_FAILED;
goto _exit;
}
_exit:
nand_close();
return status;
}
static int dump_to_buffer(void* buf)
{
int status = INSTALL_SUCCESS;
int mf_id, dev_id;
if(nand_open())
return ERR_FLASH_OPEN_FAILED;
if(nand_identify(&mf_id, &dev_id)) {
status = ERR_FLASH_OPEN_FAILED;
goto _exit;
}
if(nand_read(0, BOOT_IMAGE_SIZE, (uint8_t*)buf)) {
status = ERR_FLASH_READ_FAILED;
goto _exit;
}
_exit:
nand_close();
return status;
}
int install_bootloader(const char* path)
{
/* Allocate memory to hold image */
size_t bufsize = BOOT_IMAGE_SIZE + CACHEALIGN_SIZE - 1;
int handle = core_alloc("boot_image", bufsize);
if(handle < 0)
return ERR_OUT_OF_MEMORY;
int status = INSTALL_SUCCESS;
void* buffer = core_get_data(handle);
CACHEALIGN_BUFFER(buffer, bufsize);
/* Open the boot image */
int fd = open(path, O_RDONLY);
if(fd < 0) {
status = ERR_CANNOT_READ_FILE;
goto _exit;
}
/* Check file size */
off_t fsize = filesize(fd);
if(fsize != BOOT_IMAGE_SIZE) {
status = ERR_WRONG_SIZE;
goto _exit;
}
/* Read the file into the buffer */
ssize_t cnt = read(fd, buffer, BOOT_IMAGE_SIZE);
if(cnt != BOOT_IMAGE_SIZE) {
status = ERR_CANNOT_READ_FILE;
goto _exit;
}
/* Perform the installation */
status = install_from_buffer(buffer);
_exit:
if(fd >= 0)
close(fd);
core_free(handle);
return status;
}
/* Dump the current bootloader to a file */
int dump_bootloader(const char* path)
{
/* Allocate memory to hold image */
size_t bufsize = BOOT_IMAGE_SIZE + CACHEALIGN_SIZE - 1;
int handle = core_alloc("boot_image", bufsize);
if(handle < 0)
return -1;
/* Read data from flash */
int fd = -1;
void* buffer = core_get_data(handle);
CACHEALIGN_BUFFER(buffer, bufsize);
int status = dump_to_buffer(buffer);
if(status)
goto _exit;
/* Open file */
fd = open(path, O_CREAT|O_TRUNC|O_WRONLY);
if(fd < 0) {
status = ERR_CANNOT_WRITE_FILE;
goto _exit;
}
/* Write data to file */
ssize_t cnt = write(fd, buffer, BOOT_IMAGE_SIZE);
if(cnt != BOOT_IMAGE_SIZE) {
status = ERR_CANNOT_WRITE_FILE;
goto _exit;
}
_exit:
if(fd >= 0)
close(fd);
core_free(handle);
return status;
}
const char* installer_strerror(int rc)
{
switch(rc) {
case INSTALL_SUCCESS:
return "Success";
case ERR_FLASH_OPEN_FAILED:
return "Can't open flash device";
case ERR_FLASH_ENABLE_WP_FAILED:
return "Couldn't re-enable write protect";
case ERR_FLASH_DISABLE_WP_FAILED:
return "Can't disable write protect";
case ERR_FLASH_ERASE_FAILED:
return "Flash erase failed";
case ERR_FLASH_WRITE_FAILED:
return "Flash write error";
case ERR_FLASH_READ_FAILED:
return "Flash read error";
case ERR_OUT_OF_MEMORY:
return "Out of memory";
case ERR_CANNOT_READ_FILE:
return "Error reading file";
case ERR_CANNOT_WRITE_FILE:
return "Error writing file";
case ERR_WRONG_SIZE:
return "Wrong file size";
default:
return "Unknown error";
}
}