2018-04-07 22:43:54 +01:00
# include "utils.h"
# include "hwinit.h"
# include "fuse.h"
# include "se.h"
# include "sd_utils.h"
2018-04-08 05:51:24 +01:00
# include "stage2.h"
2018-05-04 18:21:15 +01:00
# include "sdmmc.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-04-08 05:51:24 +01:00
/* TODO: Should we allow more than 32K for the BCT0? */
# define BCT0_LOAD_ADDRESS (uintptr_t)(0x40038000)
# define BCT0_LOAD_END_ADDRESS (uintptr_t)(0x4003F000)
# define MAGIC_BCT0 0x30544342
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 " \
" stage2_addr = 0xFFF00000 \n " \
" stage2_entrypoint = 0xFFF00000 \n "
2018-04-08 06:04:30 +01:00
2018-04-08 05:51:24 +01:00
const char * load_config ( void ) {
if ( ! read_sd_file ( ( void * ) BCT0_LOAD_ADDRESS , BCT0_LOAD_END_ADDRESS - BCT0_LOAD_ADDRESS , " BCT.ini " ) ) {
2018-04-08 06:04:30 +01:00
printk ( " Failed to read BCT0 from SD! \n " ) ;
printk ( " [DEBUG] Using default BCT0! \n " ) ;
memcpy ( ( void * ) BCT0_LOAD_ADDRESS , DEFAULT_BCT0_FOR_DEBUG , sizeof ( DEFAULT_BCT0_FOR_DEBUG ) ) ;
/* 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-04-08 05:51:24 +01:00
if ( ( * ( ( u32 * ) ( BCT0_LOAD_ADDRESS ) ) ) ! = MAGIC_BCT0 ) {
printk ( " Error: Unexpected magic in BCT.ini! \n " ) ;
generic_panic ( ) ;
}
/* Return pointer to first line of the ini. */
const char * bct0 = ( const char * ) BCT0_LOAD_ADDRESS ;
while ( * bct0 & & * bct0 ! = ' \n ' ) {
bct0 + + ;
}
if ( ! bct0 ) {
printk ( " Error: BCT.ini has no newline! \n " ) ;
generic_panic ( ) ;
}
return bct0 ;
2018-04-07 22:43:54 +01:00
}
void load_sbk ( void ) {
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 ;
}
}
}
int main ( void ) {
2018-04-08 05:51:24 +01:00
stage2_entrypoint_t stage2_entrypoint ;
void * * stage2_argv = ( void * * ) ( BCT0_LOAD_END_ADDRESS ) ;
const char * bct0 ;
u32 * lfb_base ;
2018-05-04 18:21:15 +01:00
char buf [ 0x400 ] ;
memset ( buf , 0xCC , 0x400 ) ;
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-04-08 05:51:24 +01:00
/* Initialize the display. */
display_init ( ) ;
2018-05-04 20:52:38 +01:00
2018-04-08 05:51:24 +01:00
/* Register the display as a printk provider. */
lfb_base = display_init_framebuffer ( ) ;
video_init ( lfb_base ) ;
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-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 " ) ;
printk ( " Using color linear framebuffer at 0x%p! \n " , lfb_base ) ;
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
printk ( " Warning: Fus \ e9e is not yet completed, and not ready for general testing! \n " ) ;
printk ( " Please do not seek support for it until it is done. \n " ) ;
generic_panic ( ) ;
# endif
2018-05-05 16:33:49 +01:00
2018-04-07 22:43:54 +01:00
/* Try to load the SBK into the security engine, if possible. */
/* TODO: Should this be done later? */
load_sbk ( ) ;
2018-05-04 20:52:38 +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-04-08 05:51:24 +01:00
stage2_entrypoint = load_stage2 ( bct0 ) ;
2018-05-04 20:52:38 +01:00
2018-04-08 05:51:24 +01:00
/* Setup argv. */
memset ( stage2_argv , 0 , STAGE2_ARGC * sizeof ( * stage2_argv ) ) ;
2018-04-08 20:51:44 +01:00
stage2_argv [ STAGE2_ARGV_PROGRAM_PATH ] = ( void * ) stage2_get_program_path ( ) ;
stage2_argv [ STAGE2_ARGV_ARGUMENT_STRUCT ] = & stage2_argv [ STAGE2_ARGC ] ;
stage2_args_t * args = ( stage2_args_t * ) stage2_argv [ STAGE2_ARGV_ARGUMENT_STRUCT ] ;
2018-05-04 20:52:38 +01:00
2018-04-08 20:51:44 +01:00
/* Setup arguments struct. */
args - > version = 0 ;
args - > bct0 = bct0 ;
args - > lfb = ( uint32_t * ) lfb_base ;
args - > console_col = video_get_col ( ) ;
args - > console_row = video_get_row ( ) ;
2018-05-05 16:33:49 +01:00
save_sd_state ( & args - > sd_mmc ) ;
f_unmount ( " " ) ;
2018-05-04 20:52:38 +01:00
2018-04-08 05:51:24 +01:00
/* Jump to Stage 2. */
stage2_entrypoint ( STAGE2_ARGC , stage2_argv ) ;
2018-04-07 22:43:54 +01:00
return 0 ;
}