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-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-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 " \
" 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 ) {
2018-05-07 22:32:45 +01:00
if ( ! read_sd_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-04-08 05:51:24 +01:00
printk ( " Error: Unexpected magic in BCT.ini! \n " ) ;
generic_panic ( ) ;
}
/* 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 ) {
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
const char * bct0 ;
u32 * lfb_base ;
2018-05-07 22:32:45 +01:00
const char * stage2_path ;
stage2_args_t stage2_args = { 0 } ;
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. */
2018-05-07 22:32:45 +01:00
lfb_base = display_init_framebuffer ( ( void * ) 0xC0000000 ) ;
2018-04-08 05:51:24 +01:00
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-05-07 22:32:45 +01:00
load_stage2 ( bct0 ) ;
2018-05-05 16:33:49 +01:00
f_unmount ( " " ) ;
2018-05-04 20:52:38 +01:00
2018-05-07 22:32:45 +01:00
display_enable_backlight ( false ) ;
display_end ( ) ;
/* Setup argument data. */
stage2_path = stage2_get_program_path ( ) ;
stage2_args . version = 0 ;
strcpy ( stage2_args . bct0 , bct0 ) ;
strcpy ( g_chainloader_arg_data , stage2_path ) ;
memcpy ( g_chainloader_arg_data + strlen ( stage2_path ) + 1 , & stage2_args , sizeof ( stage2_args_t ) ) ;
2018-04-08 05:51:24 +01:00
/* Jump to Stage 2. */
2018-05-07 22:32:45 +01:00
relocate_and_chainload ( STAGE2_ARGC ) ;
2018-04-07 22:43:54 +01:00
return 0 ;
}