设为首页 收藏本站
查看: 1245|回复: 0

[经验分享] 如何制作支持VMWare的Windows CE BSP

[复制链接]

尚未签到

发表于 2015-4-5 16:17:12 | 显示全部楼层 |阅读模式
  不知道有没有人试过在VMWare中跑过Windows CE。可能有人会问:在VMWare中跑Windows CE有什么意义?Windows CE不是有基于Vritual PC的emulator吗?要做干吗不做一个基于Microsoft自己的Virtual PC的?
  简单的答案是,VMWare支持一些Virtual PC(包括Windows CE  emulator)不支持的硬件。对我来说,最吸引我的是VMWare支持USB设备。另外根据我的经验VMWare的性能比Virtual PC强。
  本文介绍如何针对VMWare支持的硬件,做一个相应的Windows CE  BSP。根据VMWare虚拟机的spec,我打算支持的硬件列表如下(SCSI设备、软驱这些用的比较少就算了):
  


Graphics

•VGA and SVGA support

IDE Drives

•IDE virtual disks up to 950 GB

•Serial (COM) Ports

•Up to four serial (COM) ports

USB ports

•Two-port USB 1.1 UHCI controller

Keyboard

•104-key Windows 95/98 enhanced

Mouse and Drawing Tablets

•PS/2 mouse

Ethernet Card

•AMD PCnet-PCI II compatible

Sound

•Emulates Creative Labs Sound Blaster AudioPCI (MIDI input, game controllers and joysticks are not supported, except for USB devices)

  
  
  
  其实从根本上来说,给VMWare用的Windows CE跟普通PC或者Virtual  PC的并无多大区别。因此基本做法和一些概念都可以看MSDN里对CEPC的相关介绍。这里只重点介绍一些针对VMWare的不同地方。
  给Windows CE用的VMWare虚拟机可以用DOS的。BSP可以直接copy一份Platform Builder带的CEPC BSP做为起始的BSP,然后在此基础上修改。从IDE硬盘、声卡、显卡、键盘鼠标的支持比较简单,用Platform Builder中现成的driver就行了。
DSC0000.jpg

  比较麻烦的是网卡和USB host controller。
  VMWare虚拟的网卡兼容AMD PCnet-PCI II,具体型号是AMD AM79C970A,这个在Windows CE下可实在不好找,自己写一个就太麻烦了。不过在google大法的强力帮助下,我花了很长时间终于找到一个编译好的driver-还是for Windows CE 2.0的(现在想不起来在哪儿找到的了,想要的直接找我吧)。相关注册表设置见附录。
  比较头疼的是USB host driver。VMWare中支持的USB host controller是USB 1.1 UHCI controller。Windows CE下有现成的driver,但是直接拿来用的话你会发现不能工作。一番研究后发现问题出在LEGACY SUPPORT REGISTER (LEGSUP)的设置上-VMWare在初始化UHCI controller的时候enable了SMI generation,而且没有把USB中断route到PIRQD上。简单说来就是VMWare对UHCI controller的初始化和Windows CE自带driver要求的不一样(其实是和UHCI spec定义的不一致,UHCI  spec定义LEGSUP寄存器默认值是2000h(见5.2.1节),VMWare中是3Bh)。为了能让UHCI controller工作,需要修改UHCI  driver的初始化例程,重新编译一个版本。具体修改见附录。
  这样,一个支持声卡、网卡、USB设备的VMWare BSP就基本搞定了。
  附上两张运行时的截图:
DSC0001.jpg

DSC0002.jpg
  附1,网卡的注册表设置,放在platform.reg里:


[HKEY_LOCAL_MACHINECommPCNTN4M]
    "DisplayName"="PCNTN4M Compatible Ethernet Driver"
    "Group"="NDIS"
    "ImagePath"="pcntn4m.dll"

[HKEY_LOCAL_MACHINECommPCNTN4MLinkage]
    "Route"=multi_sz:"PCNTN4M1"

[HKEY_LOCAL_MACHINECommPCNTN4M1]
    "DisplayName"="PCNTN4M Compatible Ethernet Driver"
    "Group"="NDIS"
    "ImagePath"="pcntn4m.dll"


[HKEY_LOCAL_MACHINECommPCNTN4M1Parms]
;    "BusNumber"=dword:0
;    "BusType"=dword:05
;    "Interrupt"=dword:05
;    "IOAddress"=dword:0300


[HKEY_LOCAL_MACHINECommTcpipLinkage]
      "Bind"=multi_sz:"ppp","PCNTN4M1"

    ; Registry values for the pcntn4m1 driver
[HKEY_LOCAL_MACHINECommPCNTN4M1ParmsTcpIp]
    ; This enable the DHCP. In Win CE 2.1 Preview version statically allocated IP address
       ; does not work. So we use the DHCP server to allocate the IP address.
    "EnableDHCP"=dword:1
    ; This should be MULTI_SZ
    "DefaultGateway"=""
    ; This should be SZ... If null it means use LAN, else WAN and Interface.
    "LLInterface"=""
    ; Use zero for broadcast address? (or 255.255.255.255)
    "UseZeroBroadcast"=dword:0
    ; Thus should be MULTI_SZ, the IP address list
    "IpAddress"="0.0.0.0"
    ; This should be MULTI_SZ, the subnet masks for the above IP addresses
    "Subnetmask"="0.0.0.0"

;
; Template the PCI bus driver uses to match a AM79C970 PC-net card
;
[HKEY_LOCAL_MACHINEDriversBuiltInPCITemplatePCNTN4M]
   "Dll"="NDIS.dll"
   "Class"=dword:02
   "SubClass"=dword:00
   "ProgIF"=dword:0
   "VendorID"=multi_sz:"1022"
   "DeviceID"=multi_sz:"2000"
;  "Entry"="NdisPCIBusDeviceInit"
   "Prefix"="NDS"
   "Transceiver"=dword:3
   "IsrDll"="giisr.dll"
   "IsrHandler"="ISRHandler"
   "PortIsIO"=dword:1
   "PortOffset"=dword:C        ; TBD
   "PortSize"=dword:2
   "PortMask"=dword:5F00    ; TBD

[HKEY_LOCAL_MACHINECommConnectionSharing]
   "PrivateInterface"="PCI"PCNTN4M"
  附2,UHCI driver需要修改的代码(红色部分,在$(DRIVERS)"USB"HCD"UHC"system.csystem.c中):



DSC0003.gif // Inline functions
__inline static WORD
PCIConfig_ReadWord(
                   ULONG BusNumber,
                   ULONG Device,
                   ULONG Function,
                   ULONG Offset
                   )
DSC0004.gif DSC0005.gif {
DSC0006.gif     WORD RetVal = 0;
    PCI_SLOT_NUMBER SlotNumber;

    SlotNumber.u.AsULONG = 0;
    SlotNumber.u.bits.DeviceNumber = Device;
    SlotNumber.u.bits.FunctionNumber = Function;
    HalGetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &RetVal, Offset, sizeof(RetVal));

    return RetVal;
DSC0007.gif }

__inline static void
PCIConfig_Write(
                ULONG BusNumber,
                ULONG Device,
                ULONG Function,
                ULONG Offset,
                ULONG Value,
                ULONG Size
                )
{
    PCI_SLOT_NUMBER SlotNumber;

    SlotNumber.u.AsULONG = 0;
    SlotNumber.u.bits.DeviceNumber = Device;
    SlotNumber.u.bits.FunctionNumber = Function;

    HalSetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &Value, Offset, Size);
}

/* InitializeUHCI
*
* Configure and initialize UHCI card
*
* Return Value:
* Return TRUE if card could be located and configured, otherwise FALSE
*/
static BOOL
InitializeUHCI(
               SUhcdPdd * pPddObject, // IN - Pointer to PDD structure
               LPCWSTR szDriverRegKey) // IN - Pointer to active registry key string
{
    PUCHAR ioPortBase = NULL;
    DWORD dwAddrLen;
    DWORD dwIOSpace;
    BOOL InstallIsr = FALSE;
    BOOL fResult = FALSE;
    LPVOID pobMem = NULL;
    LPVOID pobUhcd = NULL;
    DWORD PhysAddr;
    DWORD dwHPPhysicalMemSize;
    HKEY hKey;
    WORD LegSup;

    DDKWINDOWINFO dwi;
    DDKISRINFO dii;
    DDKPCIINFO dpi;
DSC0008.gif DSC0009.gif     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,szDriverRegKey,0,0,&hKey)!= ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR,(TEXT("InitializeUHCI:GetRegistryConfig RegOpenKeyEx(%s) failed "),
            szDriverRegKey));
        return FALSE;
DSC00010.gif     }
    dwi.cbSize=sizeof(dwi);
    dii.cbSize=sizeof(dii);
    dpi.cbSize=sizeof(dpi);
    if ( DDKReg_GetWindowInfo(hKey, &dwi ) !=ERROR_SUCCESS ||
        DDKReg_GetIsrInfo (hKey, &dii ) != ERROR_SUCCESS ||
        DDKReg_GetPciInfo (hKey, &dpi ) != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_ERROR,(TEXT("InitializeUHCI:DDKReg_GetWindowInfo or DDKReg_GetWindowInfo or DDKReg_GetPciInfo failed ")));
            goto InitializeUHCI_Error;
        }
    if (dwi.dwNumMemWindows!=0) {
        PhysAddr = dwi.memWindows[0].dwBase;
        dwAddrLen= dwi.memWindows[0].dwLen;
        dwIOSpace = 0;
    }
    else if (dwi.dwNumIoWindows!=0) {
        PhysAddr= dwi.ioWindows[0].dwBase;
        dwAddrLen = dwi.ioWindows[0].dwLen;
        dwIOSpace = 1;
    }
    else
        goto InitializeUHCI_Error;
    DEBUGMSG(ZONE_INIT,(TEXT("UHCD: Read config from registry: Base Address: 0x%X, Length: 0x%X, I/O Port: %s, SysIntr: 0x%X, Interface Type: %u, Bus Number: %u "),
        PhysAddr, dwAddrLen, dwIOSpace ? L"YES" : L"NO", dii.dwSysintr, dwi.dwInterfaceType, dwi.dwBusNumber));

    ioPortBase = (PUCHAR)PhysAddr;
    if (!(fResult = ConfigureUHCICard(pPddObject, &ioPortBase, dwAddrLen, dwIOSpace, dwi.dwInterfaceType, dwi.dwBusNumber))) {
        goto InitializeUHCI_Error;
    }
    if (dii.szIsrDll[0] != 0 && dii.szIsrHandler[0]!=0 && dii.dwIrq0 ) {
        // Install ISR handler
        pPddObject->IsrHandle = LoadIntChainHandler(dii.szIsrDll,dii.szIsrHandler, (BYTE)dii.dwIrq);

        if (!pPddObject->IsrHandle) {
            DEBUGMSG(ZONE_ERROR, (L"UHCD: Couldn't install ISR handler "));
        } else {
            GIISR_INFO Info;
            PHYSICAL_ADDRESS PortAddress = {PhysAddr, 0};
            DEBUGMSG(ZONE_INIT, (L"UHCD: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d ",
                dii.szIsrDll, dii.szIsrHandler, dii.dwIrq));
            if (!BusTransBusAddrToStatic(pPddObject->hParentBusHandle,dwi.dwInterfaceType, dwi.dwBusNumber, PortAddress, dwAddrLen, &dwIOSpace, &(PVOID)PhysAddr)) {
                DEBUGMSG(ZONE_ERROR, (L"UHCD: Failed TransBusAddrToStatic "));
                return FALSE;
            }
            // Set up ISR handler
            Info.SysIntr = dii.dwSysintr;
            Info.CheckPort = TRUE;
            Info.PortIsIO = (dwIOSpace) ? TRUE : FALSE;
            Info.UseMaskReg = TRUE;;
            Info.PortAddr = PhysAddr + 0x2;
            Info.PortSize = sizeof(WORD);
            Info.MaskAddr = PhysAddr + 0x4;
            if (!KernelLibIoControl(pPddObject->IsrHandle, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {
                DEBUGMSG(ZONE_ERROR, (L"UHCD: KernelLibIoControl call failed. "));
            }
        }
    }
    // The PDD can supply a buffer of contiguous physical memory here, or can let the
    // MDD try to allocate the memory from system RAM. We will use the HalAllocateCommonBuffer()
    // API to allocate the memory and bus controller physical addresses and pass this information
    // into the MDD.
    if (GetRegistryPhysicalMemSize(szDriverRegKey,&pPddObject->dwPhysicalMemSize)) {
        // A quarter for High priority Memory.
        dwHPPhysicalMemSize = pPddObject->dwPhysicalMemSize/4;
        // Align with page size.
        pPddObject->dwPhysicalMemSize = (pPddObject->dwPhysicalMemSize + PAGE_SIZE -1) & ~(PAGE_SIZE -1);
        dwHPPhysicalMemSize = ((dwHPPhysicalMemSize + PAGE_SIZE -1) & ~(PAGE_SIZE -1));
    }
    else {
        pPddObject->dwPhysicalMemSize=0;
        dwHPPhysicalMemSize = 0;
    }
    if (pPddObject->dwPhysicalMemSizedwPhysicalMemSize = gcTotalAvailablePhysicalMemory;
        dwHPPhysicalMemSize = gcHighPriorityPhysicalMemory;
    }

    pPddObject->AdapterObject.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
    pPddObject->AdapterObject.InterfaceType = dwi.dwInterfaceType;
    pPddObject->AdapterObject.BusNumber = dwi.dwBusNumber;
    if ((pPddObject->pvVirtualAddress = HalAllocateCommonBuffer(&pPddObject->AdapterObject, pPddObject->dwPhysicalMemSize, &pPddObject->LogicalAddress, FALSE)) == NULL) {
        goto InitializeUHCI_Error;
    }
    if (!(pobMem = HcdMdd_CreateMemoryObject(pPddObject->dwPhysicalMemSize, dwHPPhysicalMemSize, (PUCHAR) pPddObject->pvVirtualAddress, (PUCHAR) pPddObject->LogicalAddress.LowPart))) {
        goto InitializeUHCI_Error;
    }

    if (!(pobUhcd = HcdMdd_CreateHcdObject(pPddObject, pobMem, szDriverRegKey, ioPortBase, dii.dwSysintr))) {
        goto InitializeUHCI_Error;
    }

    // set LEGSUP here
    LegSup = PCIConfig_ReadWord(dwi.dwBusNumber, dpi.dwDeviceNumber, dpi.dwFunctionNumber, 0xC0);
    RETAILMSG(1, (TEXT("UHCD: LEGSUP=0x%08x "), LegSup));
    LegSup = 0x2000;
    PCIConfig_Write(dwi.dwBusNumber, dpi.dwDeviceNumber, dpi.dwFunctionNumber, 0xC0, LegSup, sizeof(LegSup));

    pPddObject->lpvMemoryObject = pobMem;
    pPddObject->lpvUhcdMddObject = pobUhcd;
    _tcsncpy(pPddObject->szDriverRegKey, szDriverRegKey, MAX_PATH);
    pPddObject->ioPortBase = ioPortBase;
    pPddObject->dwSysIntr = dii.dwSysintr;
    // PCI OHCI support suspend and resume
    if ( hKey!=NULL) {
        DWORD dwCapability;
        DWORD dwType;
        DWORD dwLength = sizeof(DWORD);
        if (RegQueryValueEx(hKey, HCD_CAPABILITY_VALNAME, 0, &dwType, (PUCHAR)&dwCapability, &dwLength) == ERROR_SUCCESS)
            HcdMdd_SetCapability (pobUhcd,dwCapability);
        RegCloseKey(hKey);
    }

    return TRUE;

InitializeUHCI_Error:
    if (pPddObject->IsrHandle) {
        FreeIntChainHandler(pPddObject->IsrHandle);
        pPddObject->IsrHandle = NULL;
    }
    if (pobUhcd)
        HcdMdd_DestroyHcdObject(pobUhcd);
    if (pobMem)
        HcdMdd_DestroyMemoryObject(pobMem);
    if(pPddObject->pvVirtualAddress)
        HalFreeCommonBuffer(&pPddObject->AdapterObject, pPddObject->dwPhysicalMemSize, pPddObject->LogicalAddress, pPddObject->pvVirtualAddress, FALSE);

    pPddObject->lpvMemoryObject = NULL;
    pPddObject->lpvUhcdMddObject = NULL;
    pPddObject->pvVirtualAddress = NULL;
    if ( hKey!=NULL)
        RegCloseKey(hKey);

    return FALSE;
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-54072-1-1.html 上篇帖子: VMware虛擬化技術實作問答 下篇帖子: Import VMWare Template to VMM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表