?? RIGHT := 110 ??                                                                                            
?? NEWTITLE := 'NOS/VE Analyze System: System Memory Access' ??                                               
MODULE dum$move_bytes;                                                                                        
                                                                                                              
{ PURPOSE:                                                                                                    
{   This module contains an interface to provide controlled access to system                                  
{   memory.                                                                                                   
{                                                                                                             
{ DESIGN:                                                                                                     
{   This module is intended to be part of Task Services (ring 3) and provide                                  
{   read access to system memory for the Analyze System utility running in                                    
{   user rings.  Since most NOS/VE data segments are readable from Task                                       
{   Services, most NOS/VE data will be readable through Analyze System.                                       
{                                                                                                             
{   Validation is provided on an individual user basis through a user level,                                  
{   site defined validation capability called "read_system_memory".  The                                      
{   following definitions and structured English summarize the validation                                     
{                                                                                                             
{   read_system_memory:   user_level, site defined capability                                                 
{   system_job:           indicates if request is from within system job                                      
{   system_administrator: indicates if user is running as system administrator                                
{   secure_analysis:      indicates if system is running with secure analysis                                 
{   minimum_ring:         user's minimum ring privilege                                                       
{   caller_ring:          calling programs ring of execution                                                  
{   source_ring:          ring to be used in source address                                                   
{                                                                                                             
{   IF (system_job OR system_administrator OR read_system_memory) AND                                         
{      NOT secure_analysis THEN                                                                               
{     source_ring = 1                                                                                         
{   ELSE                                                                                                      
{     source_ring = 15                                                                                        
{   IFEND                                                                                                     
{   source_ring = minimum (source_ring, minimum_ring, caller_ring)                                            
{                                                                                                             
{   Source_ring is used to form the address from which memory is read.  If                                    
{   necessary, the hardware also votes source_ring up to the ring of execution                                
{   of the memory access routine (Task Services = 3).                                                         
                                                                                                              
?? PUSH (LISTEXT := ON) ??                                                                                    
*copyc avp$get_capability                                                                                     
*copyc pmp$continue_to_cause                                                                                  
*copyc avp$ring_min                                                                                           
*copyc avp$system_administrator                                                                               
*copyc avv$security_options                                                                                   
*copyc i#move                                                                                                 
*copyc jmp$system_job                                                                                         
*copyc osd$virtual_address                                                                                    
*copyc osp$establish_condition_handler                                                                        
*copyc osp$set_status_from_condition                                                                          
*copyc ost$caller_identifier                                                                                  
?? POP ??                                                                                                     
?? NEWTITLE := '  dup$move_bytes', EJECT ??                                                                   
*copy duh$move_bytes                                                                                          
                                                                                                              
  PROCEDURE [XDCL, #GATE] dup$move_bytes (source: ^cell;                                                      
        destination: ^cell;                                                                                   
        length: 0 .. 7fffffff(16);                                                                            
    VAR status: ost$status);                                                                                  
                                                                                                              
    VAR                                                                                                       
      caller_id: ost$caller_identifier,                                                                       
      local_status: ost$status,                                                                               
      minimum_ring: ost$valid_ring,                                                                           
      read_system_memory: boolean,                                                                            
      secure_analysis: boolean,                                                                               
      source_ring: ost$valid_ring,                                                                            
      system_administrator: boolean,                                                                          
      system_job: boolean;                                                                                    
                                                                                                              
?? NEWTITLE := 'MOVE_BYTES_HANDLER', EJECT ??                                                                 
                                                                                                              
    PROCEDURE move_bytes_handler                                                                              
     (    condition: pmt$condition;                                                                           
          condition_information: ^pmt$condition_information;                                                  
          save_area: ^ost$stack_frame_save_area;                                                              
      VAR handler_status: ost$status);                                                                        
                                                                                                              
      IF (condition.selector = pmc$user_defined_condition)                                                    
{   } AND (condition.user_condition_name = osc$job_recovery_condition_name) THEN                              
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);                               
        RETURN;                                                                                               
      IFEND;                                                                                                  
                                                                                                              
      osp$set_status_from_condition ('DU', condition, save_area, status, handler_status);                     
                                                                                                              
      IF NOT handler_status.normal THEN                                                                       
        status := handler_status;                                                                             
      IFEND;                                                                                                  
                                                                                                              
      EXIT dup$move_bytes;                                                                                    
                                                                                                              
    PROCEND move_bytes_handler;                                                                               
?? OLDTITLE ??                                                                                                
?? EJECT ??                                                                                                   
                                                                                                              
    status.normal := TRUE;                                                                                    
                                                                                                              
    osp$establish_condition_handler (^move_bytes_handler, FALSE);                                             
                                                                                                              
    system_job := jmp$system_job ();                                                                          
    system_administrator := avp$system_administrator ();                                                      
                                                                                                              
    avp$get_capability (avc$read_system_memory, avc$user, read_system_memory, local_status);                  
    read_system_memory := local_status.normal AND read_system_memory;                                         
                                                                                                              
    secure_analysis := avv$security_options [avc$vso_secure_analysis].active;                                 
                                                                                                              
    IF NOT secure_analysis AND (system_job OR system_administrator OR read_system_memory) THEN                
      source_ring := osc$os_ring_1;                                                                           
    ELSE                                                                                                      
      source_ring := osc$max_ring;                                                                            
    IFEND;                                                                                                    
                                                                                                              
    minimum_ring := avp$ring_min ();                                                                          
    IF (minimum_ring < source_ring) THEN                                                                      
      source_ring := minimum_ring;                                                                            
    IFEND;                                                                                                    
                                                                                                              
    #CALLER_ID (caller_id);                                                                                   
    IF (caller_id.ring < source_ring) THEN                                                                    
      source_ring := caller_id.ring;                                                                          
    IFEND;                                                                                                    
                                                                                                              
    i#move (#address (source_ring, #segment (source), #offset (source)), destination, length);                
  PROCEND dup$move_bytes;                                                                                     
?? OLDTITLE ??                                                                                                
MODEND dum$move_bytes;                                                                                        
