15ad1c42db
- 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
210 lines
5.4 KiB
C
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";
|
|
}
|
|
}
|