2018-04-07 22:43:54 +01:00
# include "utils.h"
2018-05-20 13:11:46 +01:00
# include "panic.h"
2018-04-07 22:43:54 +01:00
# include "hwinit.h"
# include "fuse.h"
# include "se.h"
2018-05-13 22:49:50 +01:00
# include "fs_utils.h"
2018-04-08 05:51:24 +01:00
# include "stage2.h"
2018-05-07 22:32:45 +01:00
# include "chainloader.h"
2018-05-04 18:21:15 +01:00
# include "sdmmc.h"
2018-05-06 16:22:12 +01:00
# include "lib/fatfs/ff.h"
2018-04-08 05:51:24 +01:00
# include "lib/printk.h"
# include "display/video_fb.h"
2018-04-07 22:43:54 +01:00
2018-05-08 15:51:43 +01:00
extern void ( * __program_exit_callback ) ( int rc ) ;
static void * g_framebuffer ;
2018-05-07 22:32:45 +01:00
static char g_bct0_buffer [ BCTO_MAX_SIZE ] ;
2018-04-07 22:43:54 +01:00
2018-05-04 20:52:38 +01:00
# define DEFAULT_BCT0_FOR_DEBUG \
" BCT0 \n " \
" [stage1] \n " \
" stage2_path = fusee-secondary.bin \n " \
2018-05-07 22:50:30 +01:00
" stage2_addr = 0xF0000000 \n " \
" stage2_entrypoint = 0xF0000000 \n "
2018-04-08 06:04:30 +01:00
2018-05-08 15:51:43 +01:00
static const char * load_config ( void ) {
2018-05-13 22:49:50 +01:00
if ( ! read_from_file ( g_bct0_buffer , BCTO_MAX_SIZE , " BCT.ini " ) ) {
2018-04-08 06:04:30 +01:00
printk ( " Failed to read BCT0 from SD! \n " ) ;
printk ( " [DEBUG] Using default BCT0! \n " ) ;
2018-05-07 22:32:45 +01:00
memcpy ( g_bct0_buffer , DEFAULT_BCT0_FOR_DEBUG , sizeof ( DEFAULT_BCT0_FOR_DEBUG ) ) ;
2018-04-08 06:04:30 +01:00
/* TODO: Stop using default. */
/* printk("Error: Failed to load BCT.ini!\n");
* generic_panic ( ) ; */
2018-04-07 22:43:54 +01:00
}
2018-05-04 20:52:38 +01:00
2018-05-07 22:32:45 +01:00
if ( memcmp ( g_bct0_buffer , " BCT0 " , 4 ) ! = 0 ) {
2018-05-20 15:18:48 +01:00
fatal_error ( " Unexpected magic in BCT.ini! \n " ) ;
2018-04-08 05:51:24 +01:00
}
/* Return pointer to first line of the ini. */
2018-05-07 22:32:45 +01:00
const char * bct0 = g_bct0_buffer ;
2018-04-08 05:51:24 +01:00
while ( * bct0 & & * bct0 ! = ' \n ' ) {
bct0 + + ;
}
if ( ! bct0 ) {
2018-05-20 15:18:48 +01:00
fatal_error ( " BCT.ini has no newline! \n " ) ;
2018-04-08 05:51:24 +01:00
}
return bct0 ;
2018-04-07 22:43:54 +01:00
}
2018-05-08 15:51:43 +01:00
static void load_sbk ( void ) {
2018-04-07 22:43:54 +01:00
uint32_t sbk [ 0x4 ] ;
/* Load the SBK into the security engine, if relevant. */
memcpy ( sbk , ( void * ) get_fuse_chip_regs ( ) - > FUSE_PRIVATE_KEY , 0x10 ) ;
for ( unsigned int i = 0 ; i < 4 ; i + + ) {
if ( sbk [ i ] ! = 0xFFFFFFFF ) {
set_aes_keyslot ( 0xE , sbk , 0x10 ) ;
break ;
}
}
}
2018-05-08 15:51:43 +01:00
static void setup_env ( void ) {
g_framebuffer = ( void * ) 0xC0000000 ;
2018-05-04 20:52:38 +01:00
2018-04-07 22:43:54 +01:00
/* Initialize DRAM. */
/* TODO: What can be stripped out to make this minimal? */
nx_hwinit ( ) ;
2018-05-04 20:52:38 +01:00
2018-05-20 13:11:46 +01:00
/* Check for panics. */
check_and_display_panic ( ) ;
2018-05-08 15:51:43 +01:00
/* Try to load the SBK into the security engine, if possible. */
/* TODO: Should this be done later? */
load_sbk ( ) ;
2018-05-08 12:36:05 +01:00
/* Zero-fill the framebuffer and register it as printk provider. */
2018-05-08 15:51:43 +01:00
video_init ( g_framebuffer ) ;
2018-05-08 12:36:05 +01:00
2018-04-08 05:51:24 +01:00
/* Initialize the display. */
display_init ( ) ;
2018-05-04 20:52:38 +01:00
2018-05-08 12:36:05 +01:00
/* Set the framebuffer. */
2018-05-08 15:51:43 +01:00
display_init_framebuffer ( g_framebuffer ) ;
2018-05-04 20:52:38 +01:00
2018-04-08 06:04:30 +01:00
/* Turn on the backlight after initializing the lfb */
/* to avoid flickering. */
display_enable_backlight ( true ) ;
2018-05-08 15:51:43 +01:00
}
static void cleanup_env ( void ) {
f_unmount ( " " ) ;
display_enable_backlight ( false ) ;
display_end ( ) ;
}
static void exit_callback ( int rc ) {
( void ) rc ;
relocate_and_chainload ( ) ;
}
int main ( void ) {
const char * bct0 ;
const char * stage2_path ;
stage2_args_t stage2_args = { 0 } ;
/* Initialize the display, console, etc. */
setup_env ( ) ;
2018-05-04 20:52:38 +01:00
2018-04-08 05:51:24 +01:00
/* Say hello. */
printk ( " Welcome to Atmosph \xe8 re Fus \xe9 " " e! \n " ) ;
2018-05-08 15:51:43 +01:00
printk ( " Using color linear framebuffer at 0x%p! \n " , g_framebuffer ) ;
2018-05-04 20:52:38 +01:00
2018-05-04 23:35:33 +01:00
# ifndef I_KNOW_WHAT_I_AM_DOING
2018-05-04 23:38:10 +01:00
# error "Fusee is a work-in-progress bootloader, and is not ready for usage yet. If you want to play with it anyway, please #define I_KNOW_WHAT_I_AM_DOING -- and recognize that we will be unable to provide support until it is ready for general usage :)"
2018-05-04 23:35:33 +01:00
2018-05-20 15:18:48 +01:00
printk ( " Warning: Fus \xe9 " " e is not yet completed, and not ready for general testing! \n " ) ;
fatal_error ( " Please do not seek support for it until it is done. \n " ) ;
2018-05-04 23:35:33 +01:00
# endif
2018-05-05 16:33:49 +01:00
2018-04-08 05:51:24 +01:00
/* Load the BCT0 configuration ini off of the SD. */
bct0 = load_config ( ) ;
2018-05-04 20:52:38 +01:00
2018-04-07 22:43:54 +01:00
/* Load the loader payload into DRAM. */
2018-05-07 22:32:45 +01:00
load_stage2 ( bct0 ) ;
/* Setup argument data. */
stage2_path = stage2_get_program_path ( ) ;
stage2_args . version = 0 ;
strcpy ( stage2_args . bct0 , bct0 ) ;
2018-05-08 15:51:43 +01:00
g_chainloader_argc = 2 ;
2018-05-07 22:32:45 +01:00
strcpy ( g_chainloader_arg_data , stage2_path ) ;
memcpy ( g_chainloader_arg_data + strlen ( stage2_path ) + 1 , & stage2_args , sizeof ( stage2_args_t ) ) ;
2018-05-08 15:51:43 +01:00
/* Deinitialize the display, console, etc. */
cleanup_env ( ) ;
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */
__program_exit_callback = exit_callback ;
2018-04-07 22:43:54 +01:00
return 0 ;
}