Search This Blog

Thursday, December 26, 2013

Enabling PowerShell remoting

I am experimenting PowerShell remoting lately and wanted to share simple tip to enable remoting.
To enable remoting, you will want to run 'Enable-PsRemoting' cmdlet and once you run it, it asks you several questions to which you will probably want to answer 'yes'. If you want to skip this, you can run 'Enable-PsRemoting -force' and that skips question steps.

Once you have the machine ready, by default it only allows admin to execute the script so you might want to add yourself so you can execute commands from remote computer.
To add yourself, run 'Set-PSSessionConfiguration Microsoft.PowerShell -ShowSecurityDescriptorUI' cmdlet and UI will pop up and you can use that to add yourself.

Now that you have enabled remoting, let's give it a try:

PS C:\Users\ilhoye> invoke-command -computer localhost -scriptblock {ps | select -first 5 | ft}

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    124      11     2368       6068    46            2192 Acmengine
    890      42    16560      44128   150            3416 CcmExec
     46       7     1820       5140    57     0.19    532 conhost
     46       7     1844       5184    57            1664 conhost
     46       7     1824       5168    57     0.23   2844 conhost

Finally, if you still have a trouble setting up remoting, a good place to start debugging is to run 'get-help about_Remote_Troubleshooting'. This has detailed information on most issues you might encounter.


Friday, November 15, 2013

PCI Config Space with windbg

I've been working on some PCI issue and as a result I learned a bit about PCI configuration stuff. Let me summarize few things about PCI with respect to configuration.

A processor is not capable of directly accessing these config space to read from or write to.
Instead, Root complex knows how to do this when a processor makes either IO or memory access.
For example, when processor attempts to read from config space, it will try to read from certain memory-mapped IO address. This request is latched to PCI root complex which then decodes the address and figures out whether it needs to re-route the packet to appropriate secondary bus.
While the packet is in transit, its type is set to TYPE 1 but once it reaches to PCI bridge where its one of connected bus is destination bus, it changes its type to be TYPE 0.

As mentioned, we can access config space either by IO port or memory-mapped IO. To make an access via IO port, we use 0xCF8 (address port) and 0xCFC (data port).
To view if these are allocated, we can use windbg to see.
 0: kd> !arbiter 1  
 DEVNODE fffffa8009782cb0 (HTREE\ROOT\0)  
  Port Arbiter "RootPort" at fffff802e555c5a0  
   Allocated ranges:  
    0000000000000000 - 00000000000003af    
     0000000000000000 - 00000000000003af SC  fffffa80097d1d30 (pci)  
     0000000000000000 - 00000000000003af SC  fffffa80097d1d30 (pci)  
     0000000000000000 - 000000000000000f CB  fffffa8009789a50   
     0000000000000020 - 0000000000000021 CB  fffffa8009789a50   
     0000000000000040 - 0000000000000043 CB  fffffa8009789a50   
     0000000000000048 - 000000000000004b CB  fffffa8009789a50   
     0000000000000070 - 0000000000000071 CB  fffffa8009789a50   
     0000000000000080 - 000000000000008f CB  fffffa8009789a50   
     0000000000000092 - 0000000000000092 CB  fffffa8009789a50   
     00000000000000a0 - 00000000000000a1 CB  fffffa8009789a50   
     00000000000000c0 - 00000000000000cf CB  fffffa8009789a50   
     00000000000000f0 - 00000000000000ff CB  fffffa8009789a50   
    00000000000003b0 - 00000000000003df S   fffffa80097d1d30 (pci)  
    00000000000003e0 - 0000000000000cf7 S   fffffa80097d1d30 (pci)  
    0000000000000cf8 - 0000000000000cff  B  fffffa8009789a50   
    0000000000000d00 - 0000000000000fff S   fffffa80097d1d30 (pci)  
    0000000000001000 - 000000000000efff S   fffffa80097d1d30 (pci)  
   Possible allocation:  
    < none >  

We see that we have allocated resource between cf8 and cff under RootPort. Let us run a couple more debugger commands to connect again between root port and resources.
 0: kd> !devobj fffffa8009789a50  
 Device object (fffffa8009789a50) is for:  
  00000010 \Driver\PnpManager DriverObject fffffa80097560f0  
 Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040  
 Dacl fffff9a10010dd91 DevExt fffffa8009789ba0 DevObjExt fffffa8009789bb0 DevNode fffffa8009749010   
 ExtensionFlags (0x00000800) DOE_DEFAULT_SD_PRESENT  
 Characteristics (0x00000080) FILE_AUTOGENERATED_DEVICE_NAME  
 AttachedDevice (Upper) fffffa80097a34b0 \Driver\ACPI_HAL  
 Device queue is not busy.  
 0: kd> !devnode fffffa8009749010 6  
 DevNode 0xfffffa8009749010 for PDO 0xfffffa8009789a50  
  Parent 0xfffffa8009782cb0  Sibling 0xfffffa800979bd30  Child 0xfffffa800970b010    
  InstancePath is "ROOT\ACPI_HAL\0000"  
  State = DeviceNodeStarted (0x308)  
  Previous State = DeviceNodeEnumerateCompletion (0x30d)  
  StateHistory[05] = DeviceNodeEnumerateCompletion (0x30d)  
  StateHistory[04] = DeviceNodeEnumeratePending (0x30c)  
  StateHistory[03] = DeviceNodeStarted (0x308)  
 [snip]  
  StateHistory[08] = Unknown State (0x0)  
  StateHistory[07] = Unknown State (0x0)  
  StateHistory[06] = Unknown State (0x0)  
  Flags (0x0c0001f5) DNF_MADEUP, DNF_HAL_NODE,   
            DNF_ENUMERATED, DNF_IDS_QUERIED,   
            DNF_HAS_BOOT_CONFIG, DNF_BOOT_CONFIG_RESERVED,   
            DNF_NO_RESOURCE_REQUIRED, DNF_NO_LOWER_DEVICE_FILTERS,   
            DNF_NO_LOWER_CLASS_FILTERS  
  DisableableDepends = 1 (from children)  
  BootResourcesList at 0xfffff8a000069ae0 Version 0.0 Interface 0 Bus #0  
   Entry 0 - Interrupt (0x2) Driver Exclusive (0x2)  
    Flags (0000) - LEVEL_SENSITIVE   
    Level 0, Vector 0, Group 0, Affinity 0xff  
    Range starts at 0x92 for 0x1 bytes  
   Entry 56 - Port (0x1) Driver Exclusive (0x2)  
    Flags (0x11) - PORT_MEMORY PORT_IO 16_BIT_DECODE   
    Range starts at 0xa0 for 0x2 bytes  
 [snip]  
    Range starts at 0xf0 for 0x10 bytes  
   Entry 59 - Port (0x1) Driver Exclusive (0x2)  
    Flags (0x11) - PORT_MEMORY PORT_IO 16_BIT_DECODE   
    Range starts at 0xcf8 for 0x8 bytes  
   Entry 60 - Memory (0x3) Driver Exclusive (0x2)  
    Flags (0000) - READ_WRITE   
    Range starts at 0x00000000fec00000 for 0x400 bytes  
 [snip]  

So we can see how 0xCF8 and 0xCFC ports are allocated under Root Port.
If you want to see if we ever use these ports to access config space, we can set a brekpoint but these are legacy way so most likely we won't hit the breakpoint this case.
At any rate, here is how you set the breakpoint:
 0: kd> ba i4 0xcfc  
 0: kd> bl  
  1 e 00000000`00000cfc i 4 0001 (0001)  

Wednesday, October 30, 2013

Some simple change to prevent future problem

This sounds so basic but I think we always want to have a second look on our code to see if we can improve the code. For instance, I had a piece of code that takes index as input and return the value from the array. The following is hypothetical example.

 int map_func(ULONG index)  
 {  
   assert(index < max);  
   return array[index];  
 }  

When I call this function, I make sure that index is within the range. But my code interfaces with other code and as the time goes on, the code becomes pretty complicated that I had a case where input 'index' was out of range and hence, the program crashed.
So I fixed that and after a few months later, the similar issue occurred. Only then, I realized that I should have changed 'assert' to the check that would survive even in free build.
Here is the new change.
 int map_func(ULONG index)  
 {  
   if (index >= max) {  
     assert(FALSE);  
     log("error occurred: %d\n", index);  
     return -1;  
   }  
   return array[index];  
 }  

Now, I can avoid program crash in free build and also have the assert in checked build. I know this is such a simple case but I only came up with this resolution when I stopped and thought about the fix one more time.

I think I will need this stop and think moment for all my works.