@@ -33,13 +33,15 @@ use mnu_abi::mdriver_control::{
3333 MDRIVER_CONTROL_PING , MDRIVER_CONTROL_REGISTER_BLOCK_BUFFER , MDRIVER_CONTROL_START_BLOCK_QUEUE ,
3434 MDRIVER_CONTROL_START_SESSION , MDRIVER_CONTROL_STATUS_END , MDRIVER_CONTROL_STATUS_OK ,
3535 MDRIVER_CONTROL_STATUS_OUT_OF_RANGE , MDRIVER_CONTROL_STATUS_UNSUPPORTED_OPERATION ,
36- MDRIVER_CONTROL_STOP_BLOCK_QUEUE , MDRIVER_CONTROL_VERSION ,
36+ MDRIVER_CONTROL_STOP_BLOCK_QUEUE , MDRIVER_CONTROL_VERSION , MDRIVER_CONTROL_INSPECT_STORAGE ,
3737 MDRIVER_DEVICE_FEATURE_BLOCK_ASYNC_QUEUE , MDRIVER_DEVICE_FEATURE_BLOCK_FLUSH ,
3838 MDRIVER_DEVICE_FEATURE_BLOCK_READ , MDRIVER_DEVICE_FEATURE_BLOCK_WRITE ,
3939 MDRIVER_DEVICE_FEATURE_DMA_ISOLATED , MDRIVER_DEVICE_FEATURE_EPHEMERAL ,
4040 MDRIVER_DEVICE_FEATURE_INTERRUPT_ACTIVE , MDRIVER_DEVICE_FEATURE_PARTITIONED ,
4141 MDRIVER_DEVICE_FEATURE_PHYSICAL , MDRIVER_DEVICE_FEATURE_READ_ONLY , MDRIVER_DEVICE_KIND_BLOCK ,
4242 MDRIVER_DEVICE_KIND_SOUND , MDRIVER_DEVICE_STATE_ONLINE ,
43+ MDRIVER_STORAGE_QUERY_DISK , MDRIVER_STORAGE_QUERY_PARTITION_GUIDS ,
44+ MDRIVER_STORAGE_QUERY_PARTITION_RANGE ,
4345} ;
4446use mnu_abi:: shared_ring:: {
4547 initialize, pop_response, push_request, SharedRingMessage , SharedRingPage ,
@@ -50,6 +52,7 @@ static MDRIVER_EVENT_MESSAGE: &[u8] = b"mDriver control Event Channel verified\n
5052static MDRIVER_PROTOCOL_MESSAGE : & [ u8 ] = b"mDriver device control protocol ready\n " ;
5153static MDRIVER_BLOCK_MESSAGE : & [ u8 ] = b"mDriver block data path ready\n " ;
5254static MDRIVER_ASYNC_BLOCK_MESSAGE : & [ u8 ] = b"mDriver asynchronous block queue ready\n " ;
55+ static MDRIVER_STORAGE_MESSAGE : & [ u8 ] = b"mDriver read-only storage inspection ready\n " ;
5356const CONTROL_IRQ_YIELD_LIMIT : usize = 1024 ;
5457const CONTROL_REQUEST_ID : u64 = 1 ;
5558
@@ -374,12 +377,166 @@ fn start_control_protocol(boot_info: &DomainBootInfo) {
374377 initialization_failed ( boot_info)
375378 }
376379 if let Some ( ( device_id, features) ) = block_device {
380+ if features & MDRIVER_DEVICE_FEATURE_READ_ONLY != 0 {
381+ inspect_read_only_storage ( boot_info, ring, & mut request_id, device_id) ;
382+ }
377383 verify_block_data_path ( boot_info, ring, & mut request_id, device_id, features) ;
378384 verify_async_block_queue ( boot_info, ring, & mut request_id, device_id, features) ;
379385 }
380386 console_write ( boot_info, MDRIVER_PROTOCOL_MESSAGE ) ;
381387}
382388
389+ fn inspect_read_only_storage (
390+ boot_info : & DomainBootInfo ,
391+ ring : * mut SharedRingPage ,
392+ request_id : & mut u64 ,
393+ device_id : u32 ,
394+ ) {
395+ let mut report = [ 0_u8 ; 4096 ] ;
396+ let mut report_len = 0 ;
397+ append_report ( & mut report, & mut report_len, b"DISPLAY\n STORAGE READ ONLY\n " ) ;
398+ let disk = transact (
399+ boot_info,
400+ ring,
401+ request_id,
402+ MdriverControlRequest :: new (
403+ MDRIVER_CONTROL_INSPECT_STORAGE ,
404+ device_id,
405+ [ MDRIVER_STORAGE_QUERY_DISK , 0 , 0 , 0 ] ,
406+ ) ,
407+ ) ;
408+ if disk. status != MDRIVER_CONTROL_STATUS_OK
409+ || disk. values [ 2 ] == 0
410+ || disk. values [ 3 ] < MDRIVER_BLOCK_SECTOR_SIZE
411+ || !disk. values [ 3 ] . is_power_of_two ( )
412+ {
413+ initialization_failed ( boot_info)
414+ }
415+ let ( line, line_len) = storage_guid_line ( b"STORAGE DISK " , 0 , disk. values [ 0 ] , disk. values [ 1 ] ) ;
416+ console_write ( boot_info, & line[ ..line_len] ) ;
417+ append_report ( & mut report, & mut report_len, & line[ ..line_len] ) ;
418+
419+ for ordinal in 0 ..128_u64 {
420+ let guids = transact (
421+ boot_info,
422+ ring,
423+ request_id,
424+ MdriverControlRequest :: new (
425+ MDRIVER_CONTROL_INSPECT_STORAGE ,
426+ device_id,
427+ [ MDRIVER_STORAGE_QUERY_PARTITION_GUIDS , ordinal, 0 , 0 ] ,
428+ ) ,
429+ ) ;
430+ if guids. status == MDRIVER_CONTROL_STATUS_END {
431+ if ordinal > 9 {
432+ append_report ( & mut report, & mut report_len, b"MORE IN SERIAL\n " ) ;
433+ }
434+ console_write ( boot_info, & report[ ..report_len] ) ;
435+ console_write ( boot_info, MDRIVER_STORAGE_MESSAGE ) ;
436+ return ;
437+ }
438+ if guids. status != MDRIVER_CONTROL_STATUS_OK {
439+ initialization_failed ( boot_info)
440+ }
441+ let ( type_line, type_len) =
442+ storage_guid_line ( b"STORAGE TYPE " , ordinal, guids. values [ 0 ] , guids. values [ 1 ] ) ;
443+ console_write ( boot_info, & type_line[ ..type_len] ) ;
444+ if ordinal < 9 {
445+ append_report ( & mut report, & mut report_len, & type_line[ ..type_len] ) ;
446+ }
447+ let ( part_line, part_len) =
448+ storage_guid_line ( b"STORAGE PART " , ordinal, guids. values [ 2 ] , guids. values [ 3 ] ) ;
449+ console_write ( boot_info, & part_line[ ..part_len] ) ;
450+ if ordinal < 9 {
451+ append_report ( & mut report, & mut report_len, & part_line[ ..part_len] ) ;
452+ }
453+
454+ let range = transact (
455+ boot_info,
456+ ring,
457+ request_id,
458+ MdriverControlRequest :: new (
459+ MDRIVER_CONTROL_INSPECT_STORAGE ,
460+ device_id,
461+ [ MDRIVER_STORAGE_QUERY_PARTITION_RANGE , ordinal, 0 , 0 ] ,
462+ ) ,
463+ ) ;
464+ if range. status != MDRIVER_CONTROL_STATUS_OK || range. values [ 1 ] == 0 {
465+ initialization_failed ( boot_info)
466+ }
467+ let range_line = storage_range_line ( ordinal, range. values [ 0 ] , range. values [ 1 ] ) ;
468+ console_write ( boot_info, & range_line) ;
469+ if ordinal < 9 {
470+ append_report ( & mut report, & mut report_len, & range_line) ;
471+ }
472+ }
473+ initialization_failed ( boot_info)
474+ }
475+
476+ fn storage_guid_line (
477+ label : & [ u8 ; 13 ] ,
478+ ordinal : u64 ,
479+ low : u64 ,
480+ high : u64 ,
481+ ) -> ( [ u8 ; 54 ] , usize ) {
482+ let mut line = [ b' ' ; 54 ] ;
483+ line[ ..13 ] . copy_from_slice ( label) ;
484+ let mut guid = [ 0_u8 ; 16 ] ;
485+ guid[ ..8 ] . copy_from_slice ( & low. to_le_bytes ( ) ) ;
486+ guid[ 8 ..] . copy_from_slice ( & high. to_le_bytes ( ) ) ;
487+ if label == b"STORAGE DISK " {
488+ write_gpt_guid ( & mut line[ 14 ..50 ] , & guid) ;
489+ line[ 50 ] = b'\n' ;
490+ ( line, 51 )
491+ } else {
492+ write_hex_byte ( & mut line[ 13 ..15 ] , ordinal as u8 ) ;
493+ write_gpt_guid ( & mut line[ 16 ..52 ] , & guid) ;
494+ line[ 52 ] = b'\n' ;
495+ ( line, 53 )
496+ }
497+ }
498+
499+ fn storage_range_line ( ordinal : u64 , first : u64 , count : u64 ) -> [ u8 ; 52 ] {
500+ let mut line = * b"STORAGE P00 RANGE 0000000000000000 0000000000000000\n " ;
501+ write_hex_byte ( & mut line[ 9 ..11 ] , ordinal as u8 ) ;
502+ write_hex_u64 ( & mut line[ 18 ..34 ] , first) ;
503+ write_hex_u64 ( & mut line[ 35 ..51 ] , count) ;
504+ line
505+ }
506+
507+ fn append_report ( buffer : & mut [ u8 ] , length : & mut usize , value : & [ u8 ] ) {
508+ if value. len ( ) <= buffer. len ( ) . saturating_sub ( * length) {
509+ buffer[ * length..* length + value. len ( ) ] . copy_from_slice ( value) ;
510+ * length += value. len ( ) ;
511+ }
512+ }
513+
514+ fn write_gpt_guid ( output : & mut [ u8 ] , guid : & [ u8 ; 16 ] ) {
515+ const ORDER : [ usize ; 16 ] = [ 3 , 2 , 1 , 0 , 5 , 4 , 7 , 6 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ] ;
516+ let mut position = 0 ;
517+ for ( index, byte) in ORDER . iter ( ) . copied ( ) . enumerate ( ) {
518+ if matches ! ( index, 4 | 6 | 8 | 10 ) {
519+ output[ position] = b'-' ;
520+ position += 1 ;
521+ }
522+ write_hex_byte ( & mut output[ position..position + 2 ] , guid[ byte] ) ;
523+ position += 2 ;
524+ }
525+ }
526+
527+ fn write_hex_byte ( output : & mut [ u8 ] , value : u8 ) {
528+ const HEX : & [ u8 ; 16 ] = b"0123456789ABCDEF" ;
529+ output[ 0 ] = HEX [ ( value >> 4 ) as usize ] ;
530+ output[ 1 ] = HEX [ ( value & 0xf ) as usize ] ;
531+ }
532+
533+ fn write_hex_u64 ( output : & mut [ u8 ] , value : u64 ) {
534+ const HEX : & [ u8 ; 16 ] = b"0123456789ABCDEF" ;
535+ for ( index, digit) in output. iter_mut ( ) . enumerate ( ) {
536+ * digit = HEX [ ( ( value >> ( ( 15 - index) * 4 ) ) & 0xf ) as usize ] ;
537+ }
538+ }
539+
383540fn verify_block_data_path (
384541 boot_info : & DomainBootInfo ,
385542 ring : * mut SharedRingPage ,
0 commit comments