// 6. GET_DRIVE_INFO static void proc_cmd_get_drive_info(struct mg_connection* conn, const struct mg_request_info* request_info) { char str_path[200]; char str_drive[200]; get_qsvar(request_info, "path", str_path, sizeof(str_path)); sprintf(str_drive, "/odi%s", str_path); logger_remotem("GET_DRIVE_INFO: %s", str_drive); unsigned long* drive_info = getDriveInfo(str_drive); mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\n" "filesystem_size=%lu\r\n" "free_blocks=%lu\r\n" "errno=0\r\n", drive_info[0], drive_info[1]); }
// 12. GET_INFO static void proc_cmd_get_info(struct mg_connection* conn, const struct mg_request_info* request_info) { logger_remotem("GET_INFO from client: %s, version %s, ID: %s", ip2s(request_info->remote_ip), getVersion(), DVR_ID); unsigned long* drive_info = getDriveInfo(DataPath); if (DVR_ID == NULL) { logger_info("No valid ID found wait for next call: %s", DVR_ID); mg_printf(conn, "errno=51010\r\n"); return; } char tb[40]; time_t now = time(NULL); struct tm tmi; strftime(tb, 20, "%Y%m%d_%H%M%S", localtime_r(&now, &tmi)); mg_printf(conn, "HTTP/1.0 200 OK\r\n\n" "serial=%s\r\n" "version=%s\r\n" "dvr_status=%s\r\n" "battery_status=%s\r\n" "product_code=FBBW1\r\n" "filesystem_size=%lu\r\n" "free_blocks=%lu\r\n" "fg_video=%d\r\n" "mac_address=%s\r\n" "mainboard=%s\r\n" "date_time=%s\r\n" "assignable=%s\r\n" "dvr_name=%s\r\n" "errno=0\r\n", DVR_ID, getVersion(), downloading_status, get_battery_level_string(), drive_info[0], drive_info[1], getVideoCount(DataPath), getMAC(1), get_hw_version(), tb, get_assignable(), get_dvr_name()); }
static int Biosread(int biosdev, unsigned long long secno) { static int xbiosdev; static unsigned int xsec, xnsecs; struct driveInfo di; int rc = -1; int tries = 0; int bps, divisor; if (getDriveInfo(biosdev, &di) < 0) { return -1; } // Is biosdev in El Torito no emulation mode (think bootable CD's here)? if (di.no_emulation) { bps = 2048; // Yes. Assume 2K block size since the BIOS may lie about the geometry. } else { bps = di.di.params.phys_nbps; if (bps == 0) { return -1; } } divisor = bps / BPS; // _DISK_DEBUG_DUMP("Biosread dev %x sec %d bps %d\n", biosdev, secno, bps); // Use ebiosread() when supported, otherwise revert to biosread(). if ((biosdev >= kBIOSDevTypeHardDrive) && (di.uses_ebios & EBIOS_FIXED_DISK_ACCESS)) { if (cache_valid && (biosdev == xbiosdev) && (secno >= xsec) && ((unsigned int)secno < (xsec + xnsecs))) { biosbuf = trackbuf + (BPS * (secno - xsec)); return 0; } xnsecs = N_CACHE_SECS; xsec = (secno / divisor) * divisor; cache_valid = false; while ((rc = ebiosread(biosdev, secno / divisor, xnsecs / divisor)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { rc = 0; // Ignore corrected ECC errors. break; } error(" EBIOS read error: %s\n", bios_error(rc), rc); error(" Block 0x%x Sectors %d\n", secno, xnsecs); _DISK_DEBUG_SLEEP(1); } } #if LEGACY_BIOS_READ_SUPPORT else { static int xcyl, xhead; /* spc = spt * heads */ int spc = (di.di.params.phys_spt * di.di.params.phys_heads); int cyl = secno / spc; int head = (secno % spc) / di.di.params.phys_spt; int sec = secno % di.di.params.phys_spt; if (cache_valid && (biosdev == xbiosdev) && (cyl == xcyl) && (head == xhead) && ((unsigned int)sec >= xsec) && ((unsigned int)sec < (xsec + xnsecs))) { // this sector is in trackbuf cache. biosbuf = trackbuf + (BPS * (sec - xsec)); return 0; } // Cache up to a track worth of sectors, but do not cross a track boundary. xcyl = cyl; xhead = head; xsec = sec; xnsecs = ((unsigned int)(sec + N_CACHE_SECS) > di.di.params.phys_spt) ? (di.di.params.phys_spt - sec) : N_CACHE_SECS; cache_valid = false; while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { rc = 0; // Ignore corrected ECC errors. break; } error(" BIOS read error: %s\n", bios_error(rc), rc); error(" Block %d, Cyl %d Head %d Sector %d\n", secno, cyl, head, sec); _DISK_DEBUG_SLEEP(1); } } #endif // LEGACY_BIOS_READ_SUPPORT if (rc == 0) // BIOS reported success, mark sector cache as valid. { cache_valid = true; } biosbuf = trackbuf + (secno % divisor) * BPS; xbiosdev = biosdev; return rc; }
static BVRef diskScanFDiskBootVolumes( int biosdev, int * countPtr ) { const struct fdisk_part * part; struct DiskBVMap * map; int partno = -1; BVRef bvr; BVRef booterUFS = NULL; int spc; struct driveInfo di; boot_drive_info_t *dp; /* Initialize disk info */ if (getDriveInfo(biosdev, &di) != 0) { return NULL; } dp = &di.di; spc = (dp->params.phys_spt * dp->params.phys_heads); if (spc == 0) { /* This is probably a CD-ROM; punt on the geometry. */ spc = 1; } do { // Create a new mapping. map = (struct DiskBVMap *) malloc( sizeof(*map) ); if ( map ) { map->biosdev = biosdev; map->bvr = NULL; map->bvrcnt = 0; map->next = gDiskBVMap; gDiskBVMap = map; // Create a record for each partition found on the disk. while ( getNextFDiskPartition( biosdev, &partno, &part ) ) { DEBUG_DISK(("%s: part %d [%x]\n", __FUNCTION__, partno, part->systid)); bvr = 0; switch ( part->systid ) { case FDISK_UFS: bvr = newFDiskBVRef( biosdev, partno, part->relsect + UFS_FRONT_PORCH/BPS, part, UFSInitPartition, UFSLoadFile, UFSReadFile, UFSGetDirEntry, UFSGetFileBlock, UFSGetDescription, 0, kBIOSDevTypeHardDrive); break; case FDISK_HFS: bvr = newFDiskBVRef( biosdev, partno, part->relsect, part, HFSInitPartition, HFSLoadFile, HFSReadFile, HFSGetDirEntry, HFSGetFileBlock, HFSGetDescription, 0, kBIOSDevTypeHardDrive); break; case FDISK_BOOTER: booterUFS = newFDiskBVRef( biosdev, partno, ((part->relsect + spc - 1) / spc) * spc, part, UFSInitPartition, UFSLoadFile, UFSReadFile, UFSGetDirEntry, UFSGetFileBlock, UFSGetDescription, 0, kBIOSDevTypeHardDrive); break; case FDISK_NTFS: bvr = newFDiskBVRef( biosdev, partno, part->relsect, part, 0, 0, 0, 0, 0, NTFSGetDescription, 0, kBIOSDevTypeHardDrive); break; default: bvr = newFDiskBVRef( biosdev, partno, part->relsect, part, 0, 0, 0, 0, 0, 0, 0, kBIOSDevTypeHardDrive); break; } if ( bvr ) { bvr->next = map->bvr; map->bvr = bvr; map->bvrcnt++; } } // Booting from a CD with an UFS filesystem embedded // in a booter partition. if ( booterUFS ) { if ( map->bvrcnt == 0 ) { map->bvr = booterUFS; map->bvrcnt++; } else free( booterUFS ); } } } while (0); /* * If no FDisk partition, then we will check for * an Apple partition map elsewhere. */ #if UNUSED if (map->bvrcnt == 0) { static struct fdisk_part cdpart; cdpart.systid = 0xCD; /* Let's try assuming we are on a hybrid HFS/ISO9660 CD. */ bvr = newFDiskBVRef( biosdev, 0, 0, &cdpart, HFSInitPartition, HFSLoadFile, HFSReadFile, HFSGetDirEntry, HFSGetFileBlock, 0, kBIOSDevTypeHardDrive); bvr->next = map->bvr; map->bvr = bvr; map->bvrcnt++; } #endif if (countPtr) *countPtr = map ? map->bvrcnt : 0; return map ? map->bvr : NULL; }
static int Biosread( int biosdev, unsigned int secno ) { static int xbiosdev, xcyl, xhead; static unsigned int xsec, xnsecs; struct driveInfo di; int rc = -1; int cyl, head, sec; int tries = 0; int bps, divisor; if (getDriveInfo(biosdev, &di) < 0) { return -1; } if (di.no_emulation) { /* Always assume 2k block size; BIOS may lie about geometry */ bps = 2048; } else { bps = di.di.params.phys_nbps; if (bps == 0) { return -1; } } divisor = bps / BPS; DEBUG_DISK(("Biosread dev %x sec %d bps %d\n", biosdev, secno, bps)); // To read the disk sectors, use EBIOS if we can. Otherwise, // revert to the standard BIOS calls. if ((biosdev >= kBIOSDevTypeHardDrive) && (di.uses_ebios & EBIOS_FIXED_DISK_ACCESS)) { if (cache_valid && (biosdev == xbiosdev) && (secno >= xsec) && ((unsigned int)secno < (xsec + xnsecs))) { biosbuf = trackbuf + (BPS * (secno - xsec)); return 0; } xnsecs = N_CACHE_SECS; xsec = (secno / divisor) * divisor; cache_valid = FALSE; while ((rc = ebiosread(biosdev, secno / divisor, xnsecs / divisor)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { /* Ignore corrected ECC errors */ rc = 0; break; } error(" EBIOS read error: %s\n", bios_error(rc), rc); error(" Block %d Sectors %d\n", secno, xnsecs); sleep(1); } } else { /* spc = spt * heads */ int spc = (di.di.params.phys_spt * di.di.params.phys_heads); cyl = secno / spc; head = (secno % spc) / di.di.params.phys_spt; sec = secno % di.di.params.phys_spt; if (cache_valid && (biosdev == xbiosdev) && (cyl == xcyl) && (head == xhead) && ((unsigned int)sec >= xsec) && ((unsigned int)sec < (xsec + xnsecs))) { // this sector is in trackbuf cache biosbuf = trackbuf + (BPS * (sec - xsec)); return 0; } // Cache up to a track worth of sectors, but do not cross a // track boundary. xcyl = cyl; xhead = head; xsec = sec; xnsecs = ((unsigned int)(sec + N_CACHE_SECS) > di.di.params.phys_spt) ? (di.di.params.phys_spt - sec) : N_CACHE_SECS; cache_valid = FALSE; while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { /* Ignore corrected ECC errors */ rc = 0; break; } error(" BIOS read error: %s\n", bios_error(rc), rc); error(" Block %d, Cyl %d Head %d Sector %d\n", secno, cyl, head, sec); sleep(1); } } // If the BIOS reported success, mark the sector cache as valid. if (rc == 0) { cache_valid = TRUE; } biosbuf = trackbuf + (secno % divisor) * BPS; xbiosdev = biosdev; spinActivityIndicator(); return rc; }