@ -111,38 +111,29 @@ static void make_readipl(void)
ccwIplRead - > count = 0x18 ; /* Read 0x18 bytes of data */
}
static void run_readipl ( SubChannelId schid , uint16_t cutype )
static int run_readipl ( SubChannelId schid , uint16_t cutype )
{
if ( do_cio ( schid , cutype , 0x00 , CCW_FMT0 ) ) {
panic ( " dasd-ipl: Failed to run Read IPL channel program \n " ) ;
}
return do_cio ( schid , cutype , 0x00 , CCW_FMT0 ) ;
}
/*
* The architecture states that IPL1 data should consist of a psw followed by
* format - 0 READ and TIC CCWs . Let ' s sanity check .
*/
static void check_ipl1 ( void )
static bool check_ipl1 ( void )
{
Ccw0 * ccwread = ( Ccw0 * ) 0x08 ;
Ccw0 * ccwtic = ( Ccw0 * ) 0x10 ;
if ( ccwread - > cmd_code ! = CCW_CMD_DASD_READ | |
ccwtic - > cmd_code ! = CCW_CMD_TIC ) {
panic ( " dasd-ipl: IPL1 data invalid. Is this disk really bootable? \n " ) ;
}
return ( ccwread - > cmd_code = = CCW_CMD_DASD_READ & &
ccwtic - > cmd_code = = CCW_CMD_TIC ) ;
}
static void check_ipl2 ( uint32_t ipl2_addr )
static bool check_ipl2 ( uint32_t ipl2_addr )
{
Ccw0 * ccw = u32toptr ( ipl2_addr ) ;
if ( ipl2_addr = = 0x00 ) {
panic ( " IPL2 address invalid. Is this disk really bootable? \n " ) ;
}
if ( ccw - > cmd_code = = 0x00 ) {
panic ( " IPL2 ccw data invalid. Is this disk really bootable? \n " ) ;
}
return ( ipl2_addr ! = 0x00 & & ccw - > cmd_code ! = 0x00 ) ;
}
static uint32_t read_ipl2_addr ( void )
@ -188,52 +179,67 @@ static void ipl1_fixup(void)
ccwSearchTic - > cda = ptr2u32 ( ccwSearchID ) ;
}
static void run_ipl1 ( SubChannelId schid , uint16_t cutype )
static int run_ipl1 ( SubChannelId schid , uint16_t cutype )
{
uint32_t startAddr = 0x08 ;
if ( do_cio ( schid , cutype , startAddr , CCW_FMT0 ) ) {
panic ( " dasd-ipl: Failed to run IPL1 channel program \n " ) ;
}
return do_cio ( schid , cutype , startAddr , CCW_FMT0 ) ;
}
static void run_ipl2 ( SubChannelId schid , uint16_t cutype , uint32_t addr )
static int run_ipl2 ( SubChannelId schid , uint16_t cutype , uint32_t addr )
{
if ( run_dynamic_ccw_program ( schid , cutype , addr ) ) {
panic ( " dasd-ipl: Failed to run IPL2 channel program \n " ) ;
}
return run_dynamic_ccw_program ( schid , cutype , addr ) ;
}
/*
* Limitations in vfio - ccw support complicate the IPL process . Details can
* be found in docs / devel / s390 - dasd - ipl . rst
*/
void dasd_ipl ( SubChannelId schid , uint16_t cutype )
int dasd_ipl ( SubChannelId schid , uint16_t cutype )
{
PSWLegacy * pswl = ( PSWLegacy * ) 0x00 ;
uint32_t ipl2_addr ;
/* Construct Read IPL CCW and run it to read IPL1 from boot disk */
make_readipl ( ) ;
run_readipl ( schid , cutype ) ;
if ( run_readipl ( schid , cutype ) ) {
puts ( " Failed to run Read IPL channel program " ) ;
return - EIO ;
}
ipl2_addr = read_ipl2_addr ( ) ;
check_ipl1 ( ) ;
if ( ! check_ipl1 ( ) ) {
puts ( " IPL1 invalid for DASD-IPL " ) ;
return - EINVAL ;
}
/*
* Fixup IPL1 channel program to account for vfio - ccw limitations , then run
* it to read IPL2 channel program from boot disk .
*/
ipl1_fixup ( ) ;
run_ipl1 ( schid , cutype ) ;
check_ipl2 ( ipl2_addr ) ;
if ( run_ipl1 ( schid , cutype ) ) {
puts ( " Failed to run IPL1 channel program " ) ;
return - EIO ;
}
if ( ! check_ipl2 ( ipl2_addr ) ) {
puts ( " IPL2 invalid for DASD-IPL " ) ;
return - EINVAL ;
}
/*
* Run IPL2 channel program to read operating system code from boot disk
*/
run_ipl2 ( schid , cutype , ipl2_addr ) ;
if ( run_ipl2 ( schid , cutype , ipl2_addr ) ) {
puts ( " Failed to run IPL2 channel program " ) ;
return - EIO ;
}
/* Transfer control to the guest operating system */
pswl - > mask | = PSW_MASK_EAMODE ; /* Force z-mode */
pswl - > addr | = PSW_MASK_BAMODE ; /* ... */
jump_to_low_kernel ( ) ;
return - 1 ;
}