• 在Virtual Machine上运行Hello China的方法和工具


     

    在虚拟机上运行Hello China

     

    Hello China V1.5是基于传统的1.44M软盘(floppy)进行启动的。这样在开发或调试的时候十分不方便,每次都要写入软盘,并重新启动计算机。一个简便的方法是,采用虚拟机软件来模拟物理计算机,Hello China运行在虚拟机上。比如,在开发或调试用的计算机(称为宿主机)上安装虚拟机软件,并采用宿主机的物理软驱来作为虚拟机的启动设备。每次开发完毕,需要调试的时候,首先从宿主机上把编译后的Hello China影像写入软盘,并重新启动虚拟机。

    这样可大大降低物理计算机的重启次数,使得调试过程变得方便。但随着硬件的不断更新换代,在新的计算机系统上,软盘驱动器已不是必配设备。这样就给Hello China的开发和调试带来了非常大的麻烦。为解决这个问题,作为过渡解决方案,我们采用虚拟软驱加虚拟机的方式来实现Hello China的引导问题。随着Hello China的深入开发,在后续版本中,Hello China会支持硬盘、光驱(CD/DVD等)等设备的启动。

    虚拟软驱加虚拟机的解决方案十分简单,大致过程如下:

    1)  在宿主机上完成Hello China的开发或调试之后,会形成系统文件;

    2)  采用一个叫做VFMaker的程序,把系统文件写入一个虚拟软驱影像文件;

    3)  配置虚拟机软件,采用虚拟软驱影像文件来引导虚拟机。

     

    这样就不需要有物理软驱了,只要在宿主机上安装一个虚拟机软件,就很容易且快捷的实现Hello China的开发和调试。目前流行的虚拟机软件主要有Virtual PCVMWare,其中Virtual PCMicrosoft公司提供,可免费下载使用,VMWare也有免费使用版。相对Virtual PCVMWare的界面似乎更加漂亮和友好,功能更加强大一些。本文对Hello China在这两种流行的虚拟机软件上的使用方法,都做详细介绍。

     

    VFMaker程序

    VFMaker程序是一个基于C语言开发,在Visual C++ 6.0下编译的小工具。这个工具读取Hello China系统盘所需要的四个文件(bootsect.bin/realinit.bin/miniker.bin/master.bin),然后按照虚拟软驱影像文件的格式,写入一个虚拟软驱影像文件。缺省情况下,虚拟软驱影像文件的名字为VFLOPPY.VFD。当然,也可通过修改VFMaker的源代码,更改这个缺省值,或者直接在Windows文件管理器中把VFLOPPY.VFD修改为其它名字。

    下面是VMMaker程序的源代码,在VC 6.0上编译通过:

     

    //This program makes a virtual floppy image for Hello China,which is used to load Hello China in virtual PC environment.

    //It reads the four binary images,bootsect.bin,realinit.bin,miniker.bin and master.bin,into memory,and then write to a file

    //named vfloppy.vfd according to specific format.

    //

    #include <stdio.h>

    #include <stdlib.h>

    #include <windows.h>

    #include <string.h>

     

    //Macros to specify the source and destination file name.

    #define BOOTSECT_NAME TEXT("BOOTSECT.BIN")

    #define REALINIT_NAME TEXT("REALINIT.BIN")

    #define MINIKER_NAME  TEXT("MINIKER.BIN")

    #define MASTER_NAME   TEXT("MASTER.BIN")

    #define VFLOPPY_NAME  TEXT("VFLOPPY.VFD")

     

    //Constants to establish relationship between virtual floppy and physical floppy.

    #define FD_HEAD_NUM 2     //2 headers for one floppy.

    #define FD_TRACK_NUM 80   //80 tracks per header.

    #define FD_SECTOR_NUM 18  //18 sectors per track.

    #define FD_SECTOR_SIZE 512  //512 bytes per sector.

     

    //The 1.4M floppy's size.

    #define FD_SIZE (FD_HEAD_NUM * FD_TRACK_NUM * FD_SECTOR_NUM * FD_SECTOR_SIZE)

    #define FD_TRACK_SIZE (FD_SECTOR_NUM * FD_SECTOR_SIZE)  //How many bytes in one track.

     

    //This routine writes the source file to target file,which is the virtual floppy file.

    static bool WriteVf(HANDLE hBootsect,    //Handle of the bootsect file.

                      HANDLE hRealinit,    //Handle of the realinit file.

                      HANDLE hMiniker,     //Handle of the miniker file.

                      HANDLE hMaster,      //Handle of the master file.

                      HANDLE hFloppy)      //Handle of the virtual floppy file.

    {

        bool            bResult              = false;

        int             nBootsectStart       = 0;       //The bootsect resides in floppy's first sector,track 0 and header 0.

        int             nBootsectSize        = FD_SECTOR_SIZE;

        int             nRealinitStart       = 2 * FD_SECTOR_SIZE;  //The realinit resides in floppy's third sector,track 0 and hd 0.

        int             nRealinitSize        = 4096;    //Realinit.bin's size is 4K.

        int             nMinikerStart        = 10 * FD_SECTOR_SIZE; //Miniker resides in 11th sector,track 0 and header 0.

        int             nMinikerSize         = 48 * 1024;  //Miniker.bin's size is 48K.

        int             nMasterStart         = (7 * FD_SECTOR_NUM + 12) * FD_SECTOR_SIZE;  //Master resides in

                                               //track 7,sector 13,and header 0.

        int             nMasterSize          = 560 * 1024;  //Master.bin's size is 560K.

        char*           pBuffer              = NULL;

        char*           p2Buffer             = NULL;

        char*           pBuffPtr             = NULL;

        char*           p2BuffPtr            = NULL;

        unsigned long   ulRead               = 0;

        unsigned long   ulToRead             = 0;

        int             i;

     

        //Check the parameters.

        if((INVALID_HANDLE_VALUE == hBootsect)   ||

           (INVALID_HANDLE_VALUE == hRealinit)   ||

           (INVALID_HANDLE_VALUE == hMiniker)    ||

           (INVALID_HANDLE_VALUE == hMaster)     ||

           (INVALID_HANDLE_VALUE == hFloppy))

        {

           printf(TEXT("Invalid parameter(s) encounted./r/n"));

           goto __TERMINAL;

        }

        //Allocate temporary buffer.

        p2Buffer = (char*)malloc(FD_SIZE); //In Windows system,should successful.But if you like,you can allocate a small

                                           //buffer improve the success probality,and use a little more complicated algorithm

                                           //to implemente this program.

        if(NULL == p2Buffer)

        {

           printf(TEXT("Can not allocate enough memory./r/n"));

           goto __TERMINAL;

        }

        pBuffer = (char*)malloc(FD_SIZE);  //In Windows system,should successful.:-)

        if(NULL == pBuffer)

        {

           printf(TEXT("Can not allocate enough memory./r/n"));

           goto __TERMINAL;

        }

        memset(p2Buffer,0,FD_SIZE);  //Clear content of the buffer.

       

        //Now,read bootsect.bin into buffer.

        pBuffPtr = pBuffer + nBootsectStart;

        ulToRead = nBootsectSize;

        if(!ReadFile(hBootsect,

           pBuffPtr,

           ulToRead,

           &ulRead,

           NULL))  //Can not read.

        {

           printf(TEXT("Can not read bootsect.bin./r/n"));

           goto __TERMINAL;

        }

        if(ulToRead != ulRead)  //File's size may incorrect.

        {

           printf(TEXT("bootsect.bin size may incorrect./r/n"));

           goto __TERMINAL;

        }

     

        //Now,read realinit.bin into buffer.

        pBuffPtr = pBuffer + nRealinitStart;

        ulToRead = nRealinitSize;

        if(!ReadFile(hRealinit,

           pBuffPtr,

           ulToRead,

           &ulRead,

           NULL))

        {

           printf(TEXT("Can not read realinit.bin./r/n"));

           goto __TERMINAL;

        }

        if(ulToRead != ulRead)  //File's size may incorrect.

        {

           printf(TEXT("realinit.bin size may incorrect./r/n"));

           goto __TERMINAL;

        }

     

        //Now,read miniker.bin into buffer.

        pBuffPtr = pBuffer + nMinikerStart;

        ulToRead = nMinikerSize;

        if(!ReadFile(hMiniker,

           pBuffPtr,

           ulToRead,

           &ulRead,

           NULL))

        {

           printf(TEXT("Can not read miniker.bin./r/n"));

           goto __TERMINAL;

        }

        if(ulToRead != ulRead)  //File's size may incorrect.

        {

           printf(TEXT("miniker.bin's size may incorrect./r/n"));

           goto __TERMINAL;

        }

     

        //Now,read master.bin into buffer.

        pBuffPtr = pBuffer + nMasterStart;

        ulToRead = nMasterSize;

        if(!ReadFile(hMaster,

           pBuffPtr,

           ulToRead,

           &ulRead,

           NULL))

        {

           printf(TEXT("Can not read from master.bin./r/n"));

           goto __TERMINAL;

        }

        //Because the master.bin's size may change,so no need to judge it's actually size.

        //But in any case,master.bin's size must larger or equal to 64K,so we ensure it.

        if(ulRead < 64 * 1024)

        {

           printf(TEXT("master.bin size may incorrect./r/n"));

           goto __TERMINAL;

        }

     

        //I made a mistake originally,assumed the mapping relationship between physical floppy and virtual floppy file

        //is first track,second track,...,then another header. After several failures,I checked the documents related

        //to the mapping relationship,found that it is first header,first track,then second header,first track.

        //So I adjust the track sequence in pBuffer to p2Buffer,to statisfy the correct mapping relationship.If you want

        //to write a more flexible program to create a virtual floppy image,please mind this.

        //Thank windows,we can allocate any size memory block,this lets my work simple,hehe.But you also can allocate

        //a big block of memory in Hello China.:-)

        p2BuffPtr = p2Buffer;

        pBuffPtr  = pBuffer;

        for(i = 0;i < FD_TRACK_NUM * FD_HEAD_NUM;i ++)

        {

           memcpy(p2BuffPtr,pBuffPtr,FD_TRACK_SIZE);

           pBuffPtr  += FD_TRACK_SIZE;

           if(FD_TRACK_NUM - 1 == i)

           {

               p2BuffPtr = p2Buffer + FD_TRACK_SIZE;

           }

           else

           {

               p2BuffPtr += FD_TRACK_SIZE * 2;

           }

        }

       

        //Write it to virtual floppy file.

        SetFilePointer(hFloppy,0,0,FILE_BEGIN);  //Write from begin.

        if(!WriteFile(hFloppy,

           p2Buffer,

           FD_SIZE,

           &ulRead,

           NULL))

        {

           printf(TEXT("Write to Vritual Floppy File failed./r/n"));

           printf(TEXT("Please ensure no other process is using the virtual floppy file./r/n"));

           goto __TERMINAL;

        }

        if(FD_SIZE != ulRead)  //Can not write the whole buffer to file,may has not enough disk size.

        {

           printf(TEXT("The byte mount written to virtual floppy file may incorrect./r/n"));

           printf(TEXT("Please check the physical storage where the virtual floppy file residing has enough space./r/n"));

           goto __TERMINAL;

        }

        SetEndOfFile(hFloppy);

        //If reach here,the whole operation is successfully.

        bResult = true;

     

    __TERMINAL:

        if(pBuffer)

        {

           free(pBuffer);

        }

        if(p2Buffer)

        {

           free(p2Buffer);

        }

        return bResult;

    }

     

    //Main entry.

    void main()

    {

        HANDLE hBootsect     = INVALID_HANDLE_VALUE;

        HANDLE hRealinit     = INVALID_HANDLE_VALUE;

        HANDLE hMiniker      = INVALID_HANDLE_VALUE;

        HANDLE hMaster       = INVALID_HANDLE_VALUE;

        HANDLE hFloppy       = INVALID_HANDLE_VALUE;

        bool   bResult       = false;

     

        //Open all source files.

        hBootsect = CreateFile(BOOTSECT_NAME,

           GENERIC_READ,

           FILE_SHARE_DELETE,

           NULL,

           OPEN_EXISTING,

           0L,

           NULL);

        if(INVALID_HANDLE_VALUE == hBootsect)

        {

           goto __TERMINAL;

        }

     

        hRealinit = CreateFile(REALINIT_NAME,

           GENERIC_READ,

           FILE_SHARE_DELETE,

           NULL,

           OPEN_EXISTING,

           0L,

           NULL);

        if(INVALID_HANDLE_VALUE == hRealinit)

        {

           goto __TERMINAL;

        }

     

        hMiniker = CreateFile(MINIKER_NAME,

           GENERIC_READ,

           FILE_SHARE_DELETE,

           NULL,

           OPEN_EXISTING,

           0L,

           NULL);

        if(INVALID_HANDLE_VALUE == hMiniker)

        {

           goto __TERMINAL;

        }

     

        hMaster = CreateFile(MASTER_NAME,

           GENERIC_READ,

           FILE_SHARE_DELETE,

           NULL,

           OPEN_EXISTING,

           0L,

           NULL);

        if(INVALID_HANDLE_VALUE == hMaster)

        {

           goto __TERMINAL;

        }

     

        hFloppy = CreateFile(VFLOPPY_NAME,

           GENERIC_WRITE,

           FILE_SHARE_DELETE,

           NULL,

           OPEN_ALWAYS,

           0L,

           NULL);

        if(INVALID_HANDLE_VALUE == hFloppy)

        {

           goto __TERMINAL;

        }

     

        //Create virtual floppy file now.

        printf(TEXT("Writing to virtual floppy now.../r/n"));

        if(!WriteVf(hBootsect,

           hRealinit,

           hMiniker,

           hMaster,

           hFloppy))

        {

           goto __TERMINAL;

        }

     

        bResult = true;  //Mark the successful flag.

     

    __TERMINAL:

        if(hBootsect != INVALID_HANDLE_VALUE)

        {

           CloseHandle(hBootsect);

        }

        if(hRealinit != INVALID_HANDLE_VALUE)

        {

           CloseHandle(hRealinit);

        }

        if(hMiniker != INVALID_HANDLE_VALUE)

        {

           CloseHandle(hMiniker);

        }

        if(hMaster != INVALID_HANDLE_VALUE)

        {

           CloseHandle(hMaster);

        }

        if(hFloppy != INVALID_HANDLE_VALUE)

        {

           CloseHandle(hFloppy);

        }

        if(!bResult)

        {

           printf(TEXT("  Create virtual floppy image file failed./r/n"));

           printf(TEXT("  Please ensure the following file are in current directory:/r/n"));

           printf(TEXT("      bootsect.bin/r/n"));

           printf(TEXT("      realinit.bin/r/n"));

           printf(TEXT("      master.bin/r/n"));

           printf(TEXT("      miniker.bin/r/n"));

           printf(TEXT("  And make sure the virtual floppy image file is not used by other process./r/n"));

        }

        else

        {

           printf("Create virtual floppy image file (vfloppy.vfd) successfully!/r/n");

        }

    }

     

    编译后生成VFMaker.EXE文件,在使用的时候,把这个文件跟Hello China引导所需要的四个二进制文件,拷贝到同一个目录下,然后直接执行VFMaker,即可生成目标文件。下面是一个实际的抓屏结果:

     

     

    若一切正常,则该程序会提示创建虚拟软驱影像文件成功。这时候可看到当前目录下,存在一个vfloppy.vfd文件:

     

     

    若因为某种原因,导致创建VFloppy.VFD失败,则该程序也会给出提示。一般情况下,VFMaker找不到四个二进制文件中的任何一个,或者磁盘空间不够,无法创建虚拟软驱影像(1.44M),则会执行失败。如下:

     

     

    上述抓屏现实,由于少了bootsect.binrealinit.bin两个文件,导致VFMaker执行失败。

     

    虚拟软驱影像文件在Virtual PC上的使用

    虚拟软驱影像文件创建之后,在Virtual PC上的使用就非常简单了。启动Virtual PC,并创建一个虚拟机,然后启动该虚拟机。

    开始的时候,虚拟机会尝试从网络启动,这个时候可按CTRL + C终止。若找不到启动设备,虚拟机会停止启动,并提示缺少可引导设备。这时候,把虚拟软驱影像文件,用鼠标拖拽到虚拟机下面的软驱图标上,然后按任意键,就可启动了。

    下面是一个Hello China V1.5在虚拟机上的运行情况截屏:

     

     

    虚拟软驱影像文件在VMWare上的使用

     

    VMWare上的使用也非常简便,启动VMWare,并创建一个虚拟机。在创建虚拟机向导的最后一步,选择“Customize Hardware…”,增加一个虚拟软驱。缺省情况下,WMWare不会为虚拟机创建虚拟软驱。如下图:

     

     

    这时候会出现定制硬件对话框,Floppy,并选择“Use floppy image file”,给出虚拟软驱影像文件的具体位置,如下图。需要注意的是,一定要选择“Connect at power on”选项,否则虚拟机不会从虚拟软驱引导:

     

     

    完成后选择OK,就可创建一个带虚拟软驱的虚拟机了。

    创建之后,若一切正常,则虚拟机会正常引导Hello China,下面是一个引导成功后的屏幕截图:

     

     

  • 相关阅读:
    LeetCode44——用搜索的思路去理解动态规划算法
    在vscode中配置LeetCode插件,从此愉快地刷题
    分布式专题——详解Google levelDB底层原理
    高等数学——求解不定积分经典换元法
    动态规划入门——详解完全背包与多重背包问题
    详解聚类算法Kmeans的两大优化——mini-batch和Kmeans++
    Python专题——详解enumerate和zip
    LeetCode42题,单调栈、构造法、two pointers,这道Hard题的解法这么多?
    零基础学Python--------第11章 使用Python操作数据库
    零基础学Python--------第10章 文件及目录操作
  • 原文地址:https://www.cnblogs.com/fengju/p/6174263.html
Copyright © 2020-2023  润新知