VirtualBox

Changeset 93082 in vbox for trunk/src


Ignore:
Timestamp:
Dec 26, 2021 1:27:48 AM (3 years ago)
Author:
vboxsync
Message:

Main/Unattended: Detect OS/2 ISOs.

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/UnattendedImpl.h

    r91502 r93082  
    232232    HRESULT i_innerDetectIsoOSWindows(RTVFS hVfsIso, DETECTBUFFER *puBuf, VBOXOSTYPE *penmOsType);
    233233    HRESULT i_innerDetectIsoOSLinux(RTVFS hVfsIso, DETECTBUFFER *puBuf, VBOXOSTYPE *penmOsType);
     234    HRESULT i_innerDetectIsoOSOs2(RTVFS hVfsIso, DETECTBUFFER *puBuf, VBOXOSTYPE *penmOsType);
    234235
    235236    /**
  • trunk/src/VBox/Main/src-server/UnattendedImpl.cpp

    r92732 r93082  
    141141    }
    142142} UnattendedInstallationDisk;
     143
     144
     145/**
     146 * OS/2 syslevel file header.
     147 */
     148#pragma pack(1)
     149typedef struct OS2SYSLEVELHDR
     150{
     151    uint16_t    uMinusOne;          /**< 0x00: UINT16_MAX */
     152    char        achSignature[8];    /**< 0x02: "SYSLEVEL" */
     153    uint8_t     abReserved1[5];     /**< 0x0a: Usually zero. Ignore.  */
     154    uint16_t    uSyslevelFileVer;   /**< 0x0f: The syslevel file version: 1. */
     155    uint8_t     abReserved2[16];    /**< 0x11: Zero. Ignore.  */
     156    uint32_t    offTable;           /**< 0x21: Offset of the syslevel table. */
     157} OS2SYSLEVELHDR;
     158#pragma pack()
     159AssertCompileSize(OS2SYSLEVELHDR, 0x25);
     160
     161/**
     162 * OS/2 syslevel table entry.
     163 */
     164#pragma pack(1)
     165typedef struct OS2SYSLEVELENTRY
     166{
     167    uint16_t    id;                 /**< 0x00: ? */
     168    uint8_t     bEdition;           /**< 0x02: The OS/2 edition: 0=standard, 1=extended, x=component defined */
     169    uint8_t     bVersion;           /**< 0x03: 0x45 = 4.5 */
     170    uint8_t     bModify;            /**< 0x04: Lower nibble is added to bVersion, so 0x45 0x02 => 4.52 */
     171    uint8_t     abReserved1[2];     /**< 0x05: Zero. Ignore. */
     172    char        achCsdLevel[8];     /**< 0x07: The current CSD level. */
     173    char        achCsdPrior[8];     /**< 0x0f: The prior CSD level. */
     174    char        szName[80];         /**< 0x5f: System/component name. */
     175    char        achId[9];           /**< 0x67: System/component ID. */
     176    uint8_t     bRefresh;           /**< 0x70: Single digit refresh version, ignored if zero. */
     177    char        szType[9];          /**< 0x71: Some kind of type string. Optional */
     178    uint8_t     abReserved2[6];     /**< 0x7a: Zero. Ignore. */
     179} OS2SYSLEVELENTRY;
     180#pragma pack()
     181AssertCompileSize(OS2SYSLEVELENTRY, 0x80);
    143182
    144183
     
    349388    if (hrc == S_FALSE && enmOsType == VBOXOSTYPE_Unknown)
    350389        hrc = i_innerDetectIsoOSLinux(hVfsIso, &uBuf, &enmOsType);
     390    if (hrc == S_FALSE && enmOsType == VBOXOSTYPE_Unknown)
     391        hrc = i_innerDetectIsoOSOs2(hVfsIso, &uBuf, &enmOsType);
    351392    if (enmOsType != VBOXOSTYPE_Unknown)
    352393    {
     
    11811222
    11821223
     1224/**
     1225 * Detect OS/2 installation ISOs.
     1226 *
     1227 * Mainly aiming at ACP2/MCP2 as that's what we currently use in our testing.
     1228 *
     1229 * @returns COM status code.
     1230 * @retval  S_OK if detected
     1231 * @retval  S_FALSE if not fully detected.
     1232 *
     1233 * @param   hVfsIso     The ISO file system.
     1234 * @param   pBuf        Read buffer.
     1235 * @param   penmOsType  Where to return the OS type.  This is initialized to
     1236 *                      VBOXOSTYPE_Unknown.
     1237 */
     1238HRESULT Unattended::i_innerDetectIsoOSOs2(RTVFS hVfsIso, DETECTBUFFER *pBuf, VBOXOSTYPE *penmOsType)
     1239{
     1240    /*
     1241     * The OS2SE20.SRC contains the location of the tree with the diskette
     1242     * images, typically "\OS2IMAGE".
     1243     */
     1244    RTVFSFILE hVfsFile;
     1245    int vrc = RTVfsFileOpen(hVfsIso, "OS2SE20.SRC", RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &hVfsFile);
     1246    if (RT_SUCCESS(vrc))
     1247    {
     1248        size_t cbRead = 0;
     1249        vrc = RTVfsFileRead(hVfsFile, pBuf->sz, sizeof(pBuf->sz) - 1, &cbRead);
     1250        RTVfsFileRelease(hVfsFile);
     1251        if (RT_SUCCESS(vrc))
     1252        {
     1253            pBuf->sz[cbRead] = '\0';
     1254            RTStrStrip(pBuf->sz);
     1255            vrc = RTStrValidateEncoding(pBuf->sz);
     1256            if (RT_SUCCESS(vrc))
     1257                LogRelFlow(("Unattended: OS2SE20.SRC=%s\n", pBuf->sz));
     1258            else
     1259                LogRel(("Unattended: OS2SE20.SRC invalid encoding: %Rrc, %.*Rhxs\n", vrc, cbRead, pBuf->sz));
     1260        }
     1261        else
     1262            LogRel(("Unattended: Error reading OS2SE20.SRC: %\n", vrc));
     1263    }
     1264    /*
     1265     * ArcaOS has dropped the file, assume it's \OS2IMAGE and see if it's there.
     1266     */
     1267    else if (vrc == VERR_FILE_NOT_FOUND)
     1268        RTStrCopy(pBuf->sz, sizeof(pBuf->sz), "\\OS2IMAGE");
     1269    else
     1270        return S_FALSE;
     1271
     1272    /*
     1273     * Check that the directory directory exists and has a DISK_0 under it
     1274     * with an OS2LDR on it.
     1275     */
     1276    size_t const cchOs2Image = strlen(pBuf->sz);
     1277    vrc = RTPathAppend(pBuf->sz, sizeof(pBuf->sz), "DISK_0/OS2LDR");
     1278    RTFSOBJINFO ObjInfo = {0};
     1279    vrc = RTVfsQueryPathInfo(hVfsIso, pBuf->sz, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     1280    if (vrc == VERR_FILE_NOT_FOUND)
     1281    {
     1282        RTStrCat(pBuf->sz, sizeof(pBuf->sz), "."); /* eCS 2.0 image includes the dot from the 8.3 name.  */
     1283        vrc = RTVfsQueryPathInfo(hVfsIso, pBuf->sz, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     1284    }
     1285    if (   RT_FAILURE(vrc)
     1286        || !RTFS_IS_FILE(ObjInfo.Attr.fMode))
     1287    {
     1288        LogRel(("Unattended: RTVfsQueryPathInfo(, '%s' (from OS2SE20.SRC),) -> %Rrc, fMode=%#x\n",
     1289                pBuf->sz, vrc, ObjInfo.Attr.fMode));
     1290        return S_FALSE;
     1291    }
     1292
     1293    /*
     1294     * So, it's some kind of OS/2 2.x or later ISO alright.
     1295     */
     1296    *penmOsType = VBOXOSTYPE_OS2;
     1297    mStrDetectedOSHints.printf("OS2SE20.SRC=%.*s", cchOs2Image, pBuf->sz);
     1298
     1299    /*
     1300     * ArcaOS ISOs seems to have a AOSBOOT dir on them.
     1301     * This contains a ARCANOAE.FLG file with content we can use for the version:
     1302     *      ArcaOS 5.0.7 EN
     1303     *      Built 2021-12-07 18:34:34
     1304     * We drop the "ArcaOS" bit, as it's covered by penmOsType.  Then we pull up
     1305     * the second line.
     1306     *
     1307     * Note! Yet to find a way to do unattended install of ArcaOS, as it comes
     1308     *       with no CD-boot floppy images, only simple .PF archive files for
     1309     *       unpacking onto the ram disk or whatever.  Modifying these is
     1310     *       possible (ibsen's aPLib v0.36 compression with some simple custom
     1311     *       headers), but it would probably be a royal pain.  Could perhaps
     1312     *       cook something from OS2IMAGE\DISK_0 thru 3...
     1313     */
     1314    vrc = RTVfsQueryPathInfo(hVfsIso, "AOSBOOT", &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     1315    if (   RT_SUCCESS(vrc)
     1316        && RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
     1317    {
     1318        *penmOsType = VBOXOSTYPE_ArcaOS;
     1319
     1320        /* Read the version file:  */
     1321        vrc = RTVfsFileOpen(hVfsIso, "SYS/ARCANOAE.FLG", RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &hVfsFile);
     1322        if (RT_SUCCESS(vrc))
     1323        {
     1324            size_t cbRead = 0;
     1325            vrc = RTVfsFileRead(hVfsFile, pBuf->sz, sizeof(pBuf->sz) - 1, &cbRead);
     1326            RTVfsFileRelease(hVfsFile);
     1327            pBuf->sz[cbRead] = '\0';
     1328            if (RT_SUCCESS(vrc))
     1329            {
     1330                /* Strip the OS name: */
     1331                char *pszVersion = RTStrStrip(pBuf->sz);
     1332                static char s_szArcaOS[] = "ArcaOS";
     1333                if (RTStrStartsWith(pszVersion, s_szArcaOS))
     1334                    pszVersion = RTStrStripL(pszVersion + sizeof(s_szArcaOS) - 1);
     1335
     1336                /* Pull up the 2nd line if it, condensing the \r\n into a single space. */
     1337                char *pszNewLine = strchr(pszVersion, '\n');
     1338                if (pszNewLine && RTStrStartsWith(pszNewLine + 1, "Built 20"))
     1339                {
     1340                    size_t offRemove = 0;
     1341                    while (RT_C_IS_SPACE(pszNewLine[-1 - offRemove]))
     1342                        offRemove++;
     1343                    if (offRemove > 0)
     1344                    {
     1345                        pszNewLine -= offRemove;
     1346                        memmove(pszNewLine, pszNewLine + offRemove, strlen(pszNewLine + offRemove) - 1);
     1347                    }
     1348                    *pszNewLine = ' ';
     1349                }
     1350
     1351                /* Drop any additional lines: */
     1352                pszNewLine = strchr(pszVersion, '\n');
     1353                if (pszNewLine)
     1354                    *pszNewLine = '\0';
     1355                RTStrStripR(pszVersion);
     1356
     1357                /* Done (hope it makes some sense). */
     1358                mStrDetectedOSVersion = pszVersion;
     1359            }
     1360            else
     1361                LogRel(("Unattended: failed to read AOSBOOT/ARCANOAE.FLG: %Rrc\n", vrc));
     1362        }
     1363        else
     1364            LogRel(("Unattended: failed to open AOSBOOT/ARCANOAE.FLG for reading: %Rrc\n", vrc));
     1365    }
     1366    /*
     1367     * Similarly, eCS has an ECS directory and it typically contains a
     1368     * ECS_INST.FLG file with the version info.  Content differs a little:
     1369     *      eComStation 2.0 EN_US Thu May 13 10:27:54 pm 2010
     1370     *      Built on ECS60441318
     1371     * Here we drop the "eComStation" bit and leave the 2nd line as it.
     1372     *
     1373     * Note! At least 2.0 has a DISKIMGS folder with what looks like boot
     1374     *       disks, so we could probably get something going here without
     1375     *       needing to write an OS2 boot sector...
     1376     */
     1377    else
     1378    {
     1379        vrc = RTVfsQueryPathInfo(hVfsIso, "ECS", &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     1380        if (   RT_SUCCESS(vrc)
     1381            && RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
     1382        {
     1383            *penmOsType = VBOXOSTYPE_ECS;
     1384
     1385            /* Read the version file:  */
     1386            vrc = RTVfsFileOpen(hVfsIso, "ECS/ECS_INST.FLG", RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &hVfsFile);
     1387            if (RT_SUCCESS(vrc))
     1388            {
     1389                size_t cbRead = 0;
     1390                vrc = RTVfsFileRead(hVfsFile, pBuf->sz, sizeof(pBuf->sz) - 1, &cbRead);
     1391                RTVfsFileRelease(hVfsFile);
     1392                pBuf->sz[cbRead] = '\0';
     1393                if (RT_SUCCESS(vrc))
     1394                {
     1395                    /* Strip the OS name: */
     1396                    char *pszVersion = RTStrStrip(pBuf->sz);
     1397                    static char s_szECS[] = "eComStation";
     1398                    if (RTStrStartsWith(pszVersion, s_szECS))
     1399                        pszVersion = RTStrStripL(pszVersion + sizeof(s_szECS) - 1);
     1400
     1401                    /* Drop any additional lines: */
     1402                    char *pszNewLine = strchr(pszVersion, '\n');
     1403                    if (pszNewLine)
     1404                        *pszNewLine = '\0';
     1405                    RTStrStripR(pszVersion);
     1406
     1407                    /* Done (hope it makes some sense). */
     1408                    mStrDetectedOSVersion = pszVersion;
     1409                }
     1410                else
     1411                    LogRel(("Unattended: failed to read ECS/ECS_INST.FLG: %Rrc\n", vrc));
     1412            }
     1413            else
     1414                LogRel(("Unattended: failed to open ECS/ECS_INST.FLG for reading: %Rrc\n", vrc));
     1415        }
     1416        else
     1417        {
     1418            /*
     1419             * Official IBM OS/2 builds doesn't have any .FLG file on them,
     1420             * so need to pry the information out in some other way.  Best way
     1421             * is to read the SYSLEVEL.OS2 file, which is typically on disk #2,
     1422             * though on earlier versions (warp3) it was disk #1.
     1423             */
     1424            vrc = RTPathJoin(pBuf->sz, sizeof(pBuf->sz), strchr(mStrDetectedOSHints.c_str(), '=') + 1,
     1425                             "/DISK_2/SYSLEVEL.OS2");
     1426            if (RT_SUCCESS(vrc))
     1427            {
     1428                vrc = RTVfsFileOpen(hVfsIso, pBuf->sz, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &hVfsFile);
     1429                if (vrc == VERR_FILE_NOT_FOUND)
     1430                {
     1431                    RTPathJoin(pBuf->sz, sizeof(pBuf->sz), strchr(mStrDetectedOSHints.c_str(), '=') + 1, "/DISK_1/SYSLEVEL.OS2");
     1432                    vrc = RTVfsFileOpen(hVfsIso, pBuf->sz, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &hVfsFile);
     1433                }
     1434                if (RT_SUCCESS(vrc))
     1435                {
     1436                    RT_ZERO(pBuf->ab);
     1437                    size_t cbRead = 0;
     1438                    vrc = RTVfsFileRead(hVfsFile, pBuf->ab, sizeof(pBuf->ab), &cbRead);
     1439                    RTVfsFileRelease(hVfsFile);
     1440                    if (RT_SUCCESS(vrc))
     1441                    {
     1442                        /* Check the header. */
     1443                        OS2SYSLEVELHDR   const *pHdr   = (OS2SYSLEVELHDR const *)&pBuf->ab[0];
     1444                        if (   pHdr->uMinusOne == UINT16_MAX
     1445                            && pHdr->uSyslevelFileVer == 1
     1446                            && memcmp(pHdr->achSignature, RT_STR_TUPLE("SYSLEVEL")) == 0
     1447                            && pHdr->offTable < cbRead
     1448                            && pHdr->offTable + sizeof(OS2SYSLEVELENTRY) <= cbRead)
     1449                        {
     1450                            OS2SYSLEVELENTRY *pEntry = (OS2SYSLEVELENTRY *)&pBuf->ab[pHdr->offTable];
     1451                            if (   RT_SUCCESS(RTStrValidateEncodingEx(pEntry->szName, sizeof(pEntry->szName),
     1452                                                                      RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED))
     1453                                && RT_SUCCESS(RTStrValidateEncodingEx(pEntry->achCsdLevel, sizeof(pEntry->achCsdLevel), 0))
     1454                                && pEntry->bVersion != 0
     1455                                && ((pEntry->bVersion >> 4) & 0xf) < 10
     1456                                && (pEntry->bVersion & 0xf) < 10
     1457                                && pEntry->bModify  < 10
     1458                                && pEntry->bRefresh < 10)
     1459                            {
     1460                                /* Flavor: */
     1461                                char *pszName = RTStrStrip(pEntry->szName);
     1462                                if (pszName)
     1463                                    mStrDetectedOSFlavor = pszName;
     1464
     1465                                /* Version: */
     1466                                if (pEntry->bRefresh != 0)
     1467                                    mStrDetectedOSVersion.printf("%d.%d%d.%d", pEntry->bVersion >> 4, pEntry->bVersion & 0xf,
     1468                                                                 pEntry->bModify, pEntry->bRefresh);
     1469                                else
     1470                                    mStrDetectedOSVersion.printf("%d.%d%d", pEntry->bVersion >> 4, pEntry->bVersion & 0xf,
     1471                                                                 pEntry->bModify);
     1472                                pEntry->achCsdLevel[sizeof(pEntry->achCsdLevel) - 1] = '\0';
     1473                                char *pszCsd = RTStrStrip(pEntry->achCsdLevel);
     1474                                if (*pszCsd != '\0')
     1475                                {
     1476                                    mStrDetectedOSVersion.append(' ');
     1477                                    mStrDetectedOSVersion.append(pszCsd);
     1478                                }
     1479                                if (RTStrVersionCompare(mStrDetectedOSVersion.c_str(), "4.50") >= 0)
     1480                                    *penmOsType = VBOXOSTYPE_OS2Warp45;
     1481                                else if (RTStrVersionCompare(mStrDetectedOSVersion.c_str(), "4.00") >= 0)
     1482                                    *penmOsType = VBOXOSTYPE_OS2Warp4;
     1483                                else if (RTStrVersionCompare(mStrDetectedOSVersion.c_str(), "3.00") >= 0)
     1484                                    *penmOsType = VBOXOSTYPE_OS2Warp3;
     1485                            }
     1486                            else
     1487                                LogRel(("Unattended: bogus SYSLEVEL.OS2 file entry: %.128Rhxd\n", pEntry));
     1488                        }
     1489                        else
     1490                            LogRel(("Unattended: bogus SYSLEVEL.OS2 file header: uMinusOne=%#x uSyslevelFileVer=%#x achSignature=%.8Rhxs offTable=%#x vs cbRead=%#zx\n",
     1491                                    pHdr->uMinusOne, pHdr->uSyslevelFileVer, pHdr->achSignature, pHdr->offTable, cbRead));
     1492                    }
     1493                    else
     1494                        LogRel(("Unattended: failed to read SYSLEVEL.OS2: %Rrc\n", vrc));
     1495                }
     1496                else
     1497                    LogRel(("Unattended: failed to open '%s' for reading: %Rrc\n", pBuf->sz, vrc));
     1498            }
     1499        }
     1500    }
     1501
     1502    /** @todo language detection? */
     1503
     1504    /** @todo Return true if we can actually do an unattended installation
     1505     *        using this ISO.  So far, we cannot from any OS/2 image. */
     1506    return S_FALSE;
     1507}
     1508
     1509
    11831510HRESULT Unattended::prepare()
    11841511{
  • trunk/src/VBox/Main/src-server/UnattendedInstaller.cpp

    r91718 r93082  
    6565        else
    6666            pUinstaller = new UnattendedWindowsSifInstaller(pParent);
     67    }
     68    else if (enmOsType >= VBOXOSTYPE_OS2 && enmOsType < VBOXOSTYPE_Linux)
     69    {
     70        /** @todo OS/2 */
    6771    }
    6872    else
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette