Settings::~Settings() { // only save the settings if something has changed if (!fUpdated) return; BFile file; if (Open(&file, B_CREATE_FILE | B_WRITE_ONLY) != B_OK) return; disk_probe_settings settings; settings.window_frame = fMessage.FindRect("window_frame"); #if B_HOST_IS_BENDIAN // settings are saved in little endian settings.window_frame.left = B_HOST_TO_LENDIAN_FLOAT( settings.window_frame.left); settings.window_frame.top = B_HOST_TO_LENDIAN_FLOAT( settings.window_frame.top); settings.window_frame.right = B_HOST_TO_LENDIAN_FLOAT( settings.window_frame.right); settings.window_frame.bottom = B_HOST_TO_LENDIAN_FLOAT( settings.window_frame.bottom); #endif settings.base_type = B_HOST_TO_LENDIAN_INT32( fMessage.FindInt32("base_type")); settings.font_size = B_HOST_TO_LENDIAN_INT32( int32(fMessage.FindFloat("font_size") + 0.5f)); settings.flags = B_HOST_TO_LENDIAN_INT32( (fMessage.FindBool("case_sensitive") ? kCaseSensitive : 0) | (fMessage.FindInt8("find_mode") == kHexMode ? kHexFindMode : 0)); file.Write(&settings, sizeof(settings)); }
void MMFlattenMessage(const MMessage * msg, void * outBuf) { /* Format: 0. Protocol revision number (4 bytes, always set to CURRENT_PROTOCOL_VERSION) */ /* 1. 'what' code (4 bytes) */ /* 2. Number of entries (4 bytes) */ /* 3. Entry name length (4 bytes) */ /* 4. Entry name string (flattened String) */ /* 5. Entry type code (4 bytes) */ /* 6. Entry data length (4 bytes) */ /* 7. Entry data (n bytes) */ /* 8. loop to 3 as necessary */ /* Write current protocol version */ uint32 writeOffset = 0; { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(CURRENT_PROTOCOL_VERSION); WriteData(outBuf, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write 'what' code */ { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(msg->what); WriteData(outBuf, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Calculate the number of flattenable entries (may be less than the total number of entries!) */ { uint32 numFlattenableEntries = 0; { const MMessageField * f = msg->firstField; while(f) { if (f->isFlattenable) numFlattenableEntries++; f = f->nextField; } } /* Write number of entries */ { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(numFlattenableEntries); WriteData(outBuf, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write entries */ { const MMessageField * f = msg->firstField; while(f) { if (f->isFlattenable) writeOffset += FlattenMMessageField(f, &((char *)outBuf)[writeOffset]); f = f->nextField; } } } /*printf("%s "UINT32_FORMAT_SPEC"/"UINT32_FORMAT_SPEC"\n", (writeOffset != MMGetFlattenedSize(msg))?"ERROR":"ok", writeOffset, MMGetFlattenedSize(msg)); DEBUG */ }
int32 PacketizedProxyDataIO :: Write(const void * buffer, uint32 size) { if (size > _maxTransferUnit) { LogTime(MUSCLE_LOG_ERROR, "PacketizedProxyDataIO: Error, tried to send packet with size " UINT32_FORMAT_SPEC ", max transfer unit is set to " UINT32_FORMAT_SPEC "\n", size, _maxTransferUnit); return -1; } // Only accept more data if we are done sending the data we already have buffered up bool tryAgainAfter = false; int32 ret = 0; if (HasBufferedOutput()) tryAgainAfter = true; else { // No data buffered? _outputBufferBytesSent = 0; if (_outputBuffer.SetNumBytes(sizeof(uint32)+size, false) != B_NO_ERROR) return 0; muscleCopyOut(_outputBuffer.GetBuffer(), B_HOST_TO_LENDIAN_INT32(size)); memcpy(_outputBuffer.GetBuffer()+sizeof(uint32), buffer, size); ret = size; } if (WriteBufferedOutputAux() != B_NO_ERROR) return -1; return ((tryAgainAfter)&&(HasBufferedOutput() == false)) ? Write(buffer, size) : ret; }
void PCL6Writer::Append(uint32 value) { int32 v = B_HOST_TO_LENDIAN_INT32(value); Append(BYTE_AT(v, 0)); Append(BYTE_AT(v, 1)); Append(BYTE_AT(v, 2)); Append(BYTE_AT(v, 3)); }
uint16 Volume::_GroupCheckSum(ext2_block_group *group, int32 index) { uint16 checksum = 0; if (HasChecksumFeature()) { int32 number = B_HOST_TO_LENDIAN_INT32(index); checksum = calculate_crc(0xffff, fSuperBlock.uuid, sizeof(fSuperBlock.uuid)); checksum = calculate_crc(checksum, (uint8*)&number, sizeof(number)); checksum = calculate_crc(checksum, (uint8*)group, 30); if (Has64bitFeature()) { checksum = calculate_crc(checksum, (uint8*)group + 34, fGroupDescriptorSize - 34); } } return checksum; }
void MemoryView::_GetNextHexBlock(char* buffer, int32 bufferSize, const char* address) { switch(fHexMode) { case HexMode8BitInt: { snprintf(buffer, bufferSize, "%02" B_PRIx8, *((const uint8*)address)); break; } case HexMode16BitInt: { uint16 data = *((const uint16*)address); switch(fCurrentEndianMode) { case EndianModeBigEndian: { data = B_HOST_TO_BENDIAN_INT16(data); } break; case EndianModeLittleEndian: { data = B_HOST_TO_LENDIAN_INT16(data); } break; } snprintf(buffer, bufferSize, "%04" B_PRIx16, data); break; } case HexMode32BitInt: { uint32 data = *((const uint32*)address); switch(fCurrentEndianMode) { case EndianModeBigEndian: { data = B_HOST_TO_BENDIAN_INT32(data); } break; case EndianModeLittleEndian: { data = B_HOST_TO_LENDIAN_INT32(data); } break; } snprintf(buffer, bufferSize, "%08" B_PRIx32, data); break; } case HexMode64BitInt: { uint64 data = *((const uint64*)address); switch(fCurrentEndianMode) { case EndianModeBigEndian: { data = B_HOST_TO_BENDIAN_INT64(data); } break; case EndianModeLittleEndian: { data = B_HOST_TO_LENDIAN_INT64(data); } break; } snprintf(buffer, bufferSize, "%0*" B_PRIx64, 16, data); break; } } }
int32 PacketTunnelIOGateway :: DoOutputImplementation(uint32 maxBytes) { if (_outputPacketBuffer.SetNumBytes(_maxTransferUnit, false) != B_NO_ERROR) return -1; uint32 totalBytesWritten = 0; bool firstTime = true; while((totalBytesWritten < maxBytes)&&((firstTime)||(IsSuggestedTimeSliceExpired() == false))) { firstTime = false; // Step 1: Add as much data to our output packet buffer as we can fit into it while((_outputPacketSize+FRAGMENT_HEADER_SIZE < _maxTransferUnit)&&(HasBytesToOutput())) { // Demand-create the next send-buffer if (_currentOutputBuffer() == NULL) { MessageRef msg; if (GetOutgoingMessageQueue().RemoveHead(msg) == B_NO_ERROR) { _currentOutputBufferOffset = 0; _currentOutputBuffer.Reset(); if (_slaveGateway()) { DataIORef oldIO = _slaveGateway()->GetDataIO(); // save slave gateway's old state // Get the slave gateway to generate its output into our ByteBuffer _fakeSendBuffer.SetNumBytes(0, false); _fakeSendIO.Seek(0, SeekableDataIO::IO_SEEK_SET); _slaveGateway()->SetDataIO(DataIORef(&_fakeSendIO, false)); _slaveGateway()->AddOutgoingMessage(msg); while(_slaveGateway()->DoOutput() > 0) {/* empty */} _slaveGateway()->SetDataIO(oldIO); // restore slave gateway's old state _currentOutputBuffer.SetRef(&_fakeSendBuffer, false); } else if (_fakeSendBuffer.SetNumBytes(msg()->FlattenedSize(), false) == B_NO_ERROR) { // Default algorithm: Just flatten the Message into the buffer msg()->Flatten(_fakeSendBuffer.GetBuffer()); _currentOutputBuffer.SetRef(&_fakeSendBuffer, false); } } } if (_currentOutputBuffer() == NULL) break; // oops, out of mem? uint32 sbSize = _currentOutputBuffer()->GetNumBytes(); uint32 dataBytesToSend = muscleMin(_maxTransferUnit-(_outputPacketSize+FRAGMENT_HEADER_SIZE), sbSize-_currentOutputBufferOffset); uint8 * p = _outputPacketBuffer.GetBuffer()+_outputPacketSize; muscleCopyOut(&p[0*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_magic)); // a well-known magic number, for sanity checking muscleCopyOut(&p[1*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_sexID)); // source exclusion ID muscleCopyOut(&p[2*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_sendMessageIDCounter)); // message ID tag so the receiver can track what belongs where muscleCopyOut(&p[3*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_currentOutputBufferOffset)); // start offset (within its message) for this sub-chunk muscleCopyOut(&p[4*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(dataBytesToSend)); // size of this sub-chunk muscleCopyOut(&p[5*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(sbSize)); // total size of this message //printf("CREATING PACKET magic=" UINT32_FORMAT_SPEC " msgID=" UINT32_FORMAT_SPEC " offset=" UINT32_FORMAT_SPEC " chunkSize=" UINT32_FORMAT_SPEC " totalSize=" UINT32_FORMAT_SPEC "\n", _magic, _sendMessageIDCounter, _currentOutputBufferOffset, dataBytesToSend, sbSize); memcpy(p+FRAGMENT_HEADER_SIZE, _currentOutputBuffer()->GetBuffer()+_currentOutputBufferOffset, dataBytesToSend); _outputPacketSize += (FRAGMENT_HEADER_SIZE+dataBytesToSend); _currentOutputBufferOffset += dataBytesToSend; if (_currentOutputBufferOffset == sbSize) { _currentOutputBuffer.Reset(); _fakeSendBuffer.Clear(_fakeSendBuffer.GetNumBytes() > MAX_CACHE_SIZE); // don't keep too much memory around! _sendMessageIDCounter++; } } // Step 2: If we have a non-empty packet to send, send it! if (_outputPacketSize > 0) { // If bytesWritten is set to zero, we just hold this buffer until our next call. int32 bytesWritten = GetDataIO()()->Write(_outputPacketBuffer.GetBuffer(), _outputPacketSize); //printf("WROTE " INT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " bytes %s\n", bytesWritten, _outputPacketSize, (bytesWritten==(int32)_outputPacketSize)?"":"******** SHORT ***********"); if (bytesWritten > 0) { if (bytesWritten != (int32)_outputPacketSize) LogTime(MUSCLE_LOG_ERROR, "PacketTunnelIOGateway::DoOutput(): Short write! (" INT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " bytes)\n", bytesWritten, _outputPacketSize); _outputPacketBuffer.Clear(); _outputPacketSize = 0; totalBytesWritten += bytesWritten; } else if (bytesWritten == 0) break; // no more space to write, for now else return -1; } else break; // nothing more to do! } return totalBytesWritten; }
bool TRIFFWriter::InitAVIFile() { // We cannot write out if all elements are not initialized... off_t savePos; bool retVal = true; ssize_t size = 0x4949; // Rewind the file m_File->Seek(0, SEEK_SET); // Write RIFF header WriteRIFFChunk(size); // Write AVIHeader LIST chunk retVal = WriteLISTChunk(size); if (retVal == false) return retVal; // Save position for later calculation. Back over size... off_t listHeaderPos = m_File->Position(); listHeaderPos -= sizeof(uint32); WriteIntMsb(m_File, kRiff_hdrl_Chunk, sizeof(uint32)); // Write AVIHeader chunk retVal = WriteavihChunk(); if (retVal == false) return retVal; // // Write stream data List Chunk // // Make sure we have streams to write if ( (m_StreamCount == 0) || (m_StreamCount > kRiffWriteMaxStreams) ) return false; // // Write out first stream // retVal = WriteLISTChunk(size); if (retVal == false) return retVal; // Save position for later size calculation off_t streamOnePos = m_File->Position(); // Write out 'strl' chunk WriteIntMsb(m_File, kRiff_strl_Chunk, sizeof(uint32)); // First stream header retVal = WriteStreamHeader(&m_StreamHeaderOne); // First stream format retVal = WriteStreamFormat(&m_StreamHeaderOne); // Update streamOne chunk size savePos = m_File->Position(); uint32 streamOneSize = (uint32)(savePos - streamOnePos); // Update list header chunk size B_HOST_TO_LENDIAN_INT32(streamOneSize); streamOnePos -= sizeof(uint32); m_File->WriteAt(streamOnePos, &streamOneSize, sizeof(uint32)); // Return to saved postion m_File->Seek(savePos, SEEK_SET); // // Write out second stream // if (m_StreamCount == 2) { retVal = WriteLISTChunk(size); if (retVal == false) return retVal; // Save position for later size calculation off_t streamTwoPos = m_File->Position(); // Write out 'strl' chunk WriteIntMsb(m_File, kRiff_strl_Chunk, sizeof(uint32)); // Second stream header retVal = WriteStreamHeader(&m_StreamHeaderTwo); // Second stream format retVal = WriteStreamFormat(&m_StreamHeaderTwo); // Update streamTwo chunk size savePos = m_File->Position(); uint32 streamTwoSize = savePos - streamTwoPos; // Update list header chunk size B_HOST_TO_LENDIAN_INT32(streamTwoSize); streamTwoPos -= sizeof(uint32); m_File->WriteAt(streamTwoPos, &streamTwoSize, sizeof(uint32)); // Restore position m_File->Seek(savePos, SEEK_SET); } // Save position and go back and update unitialized chunk sizes savePos = m_File->Position(); uint32 listHeaderSize = savePos - listHeaderPos; // Update list header chunk size B_HOST_TO_LENDIAN_INT32(listHeaderSize); m_File->WriteAt(listHeaderPos, &listHeaderSize, sizeof(uint32)); // Restore position m_File->Seek(savePos, SEEK_SET); // // Write movi Chunk. We don't know the true size yet... // retVal = WriteLISTChunk(size); if (retVal == false) return retVal; WriteIntMsb(m_File, kRiff_movi_Chunk, sizeof(uint32)); // Save offset for later index chunk calculation m_MoviChunkOffset = m_File->Position(); // All done return retVal; }
bool TRIFFWriter::CompleteAVIFile() { bool retVal = true; uint32 streamSize; // Save our position off_t savePos = m_File->Position(); // Rewind m_File->Seek(0, SEEK_SET); // Skip over RIFF form m_File->Seek(sizeof(uint32), SEEK_CUR); // Write file size and bump pointer off_t fileSize; m_File->GetSize(&fileSize); uint32 size = (uint32)fileSize; B_HOST_TO_LENDIAN_INT32(size); m_File->WriteAt(m_File->Position(), &size, sizeof(uint32)); m_File->Seek( sizeof(uint32), SEEK_CUR); // Skip AVI form, LIST chunk and hdrl chunk m_File->Seek( sizeof(uint32) * 6, SEEK_CUR); // // Update unitialized AVIHeader fields // // Skip filled fields and update fields needing info m_File->Seek( sizeof(uint32) * 4, SEEK_CUR); WriteAtIntLsb(m_File, m_TotalFrames, sizeof(uint32)); m_File->Seek( sizeof(uint32), SEEK_CUR); m_File->Seek( sizeof(uint32) * 8, SEEK_CUR); WriteAtIntLsb(m_File, m_TotalFrames, sizeof(uint32)); m_File->Seek( sizeof(uint32), SEEK_CUR); // // Update unitialized stream header and format fields // // The first should always be the video stream // Skip LIST chunk m_File->Seek( sizeof(uint32) * 3, SEEK_CUR); // Skip stream header chunkID and size m_File->Seek( sizeof(uint32) * 2, SEEK_CUR); // Skip filled fields and update DataLength. Skip over rest of chunk... m_File->Seek( sizeof(uint32) * 8, SEEK_CUR); WriteAtIntLsb(m_File, m_TotalFrames, sizeof(uint32)); m_File->Seek( sizeof(uint32) * 4, SEEK_CUR); // Skip vids StreamFormat chunk m_File->Seek( sizeof(uint32), SEEK_CUR); m_File->Read( &streamSize, sizeof(uint32)); m_File->Seek(streamSize, SEEK_CUR); // Is there an audio chunk to update? If so, it will always be the second stream if ( m_StreamCount > 1) { // Skip LIST chunk m_File->Seek( sizeof(uint32) * 3, SEEK_CUR); // Skip stream header m_File->Seek( sizeof(uint32), SEEK_CUR); m_File->Read( &streamSize, sizeof(uint32)); m_File->Seek(streamSize, SEEK_CUR); // Skip stream format header and size m_File->Seek( sizeof(uint32) * 2, SEEK_CUR); // Skip filled fields and update ByteCount m_File->Seek( 28, SEEK_CUR); WriteAtIntLsb(m_File, m_AUDSHeader.ByteCount, sizeof(uint32)); m_File->Seek( sizeof(uint32), SEEK_CUR); } // // Write out size of 'movi' chunk // // Seek to start of 'movi' index off_t seekPos = m_MoviChunkOffset - ( sizeof(uint32) * 2); m_File->Seek(seekPos, SEEK_SET); // Calculate movi chunk size and write it out m_File->GetSize(&fileSize); size = (uint32)fileSize; uint32 moviChunkSize = size - m_MoviChunkOffset; moviChunkSize += sizeof(uint32); WriteAtIntLsb(m_File, moviChunkSize, sizeof(uint32)); m_File->Seek( sizeof(uint32), SEEK_CUR); // Go to end of file and write out index chunk m_File->Seek(0, SEEK_END); retVal = Writeidx1Chunk(); return retVal; }
status_t pll_set(display_mode* mode, uint8 crtcID) { uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; pll_info* pll = &gConnector[connectorIndex]->encoder.pll; uint32 dp_clock = gConnector[connectorIndex]->dpInfo.linkRate; bool ssEnabled = false; pll->pixelClock = mode->timing.pixel_clock; radeon_shared_info &info = *gInfo->shared_info; // Probe for PLL spread spectrum info; pll->ssPercentage = 0; pll->ssType = 0; pll->ssStep = 0; pll->ssDelay = 0; pll->ssRange = 0; pll->ssReferenceDiv = 0; switch (display_get_encoder_mode(connectorIndex)) { case ATOM_ENCODER_MODE_DP_MST: case ATOM_ENCODER_MODE_DP: if (info.dceMajor >= 4) pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_DP); else { if (dp_clock == 162000) { ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID2); if (!ssEnabled) // id2 failed, try id1 ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1); } else ssEnabled = pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1); } break; case ATOM_ENCODER_MODE_LVDS: if (info.dceMajor >= 4) ssEnabled = pll_asic_ss_probe(pll, gInfo->lvdsSpreadSpectrumID); else ssEnabled = pll_ppll_ss_probe(pll, gInfo->lvdsSpreadSpectrumID); break; case ATOM_ENCODER_MODE_DVI: if (info.dceMajor >= 4) ssEnabled = pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_TMDS); break; case ATOM_ENCODER_MODE_HDMI: if (info.dceMajor >= 4) ssEnabled = pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_HDMI); break; } pll_setup_flags(pll, crtcID); // set up any special flags pll_adjust(pll, mode, crtcID); // get any needed clock adjustments, set reference/post dividers pll_compute(pll); // compute dividers display_crtc_ss(pll, ATOM_DISABLE); // disable ss uint8 tableMajor; uint8 tableMinor; int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor); TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor); uint32 bitsPerColor = 8; // TODO: Digital Depth, EDID 1.4+ on digital displays // isn't in Haiku edid common code? // Prepare arguments for AtomBIOS call union setPixelClock { SET_PIXEL_CLOCK_PS_ALLOCATION base; PIXEL_CLOCK_PARAMETERS v1; PIXEL_CLOCK_PARAMETERS_V2 v2; PIXEL_CLOCK_PARAMETERS_V3 v3; PIXEL_CLOCK_PARAMETERS_V5 v5; PIXEL_CLOCK_PARAMETERS_V6 v6; }; union setPixelClock args; memset(&args, 0, sizeof(args)); switch (tableMinor) { case 1: args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv); args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v1.ucFracFbDiv = pll->feedbackDivFrac; args.v1.ucPostDiv = pll->postDiv; args.v1.ucPpll = pll->id; args.v1.ucCRTC = crtcID; args.v1.ucRefDivSrc = 1; break; case 2: args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv); args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v2.ucFracFbDiv = pll->feedbackDivFrac; args.v2.ucPostDiv = pll->postDiv; args.v2.ucPpll = pll->id; args.v2.ucCRTC = crtcID; args.v2.ucRefDivSrc = 1; break; case 3: args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv); args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v3.ucFracFbDiv = pll->feedbackDivFrac; args.v3.ucPostDiv = pll->postDiv; args.v3.ucPpll = pll->id; args.v3.ucMiscInfo = (pll->id << 2); if (pll->ssPercentage > 0 && (pll->ssType & ATOM_EXTERNAL_SS_MASK) != 0) { args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; } args.v3.ucTransmitterId = gConnector[connectorIndex]->encoder.objectID; args.v3.ucEncoderMode = display_get_encoder_mode(connectorIndex); break; case 5: args.v5.ucCRTC = crtcID; args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v5.ucRefDiv = pll->referenceDiv; args.v5.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v5.ulFbDivDecFrac = B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000); args.v5.ucPostDiv = pll->postDiv; args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ if (pll->ssPercentage > 0 && (pll->ssType & ATOM_EXTERNAL_SS_MASK) != 0) { args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC; } switch (bitsPerColor) { case 8: default: args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; break; case 10: args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; break; } args.v5.ucTransmitterID = gConnector[connectorIndex]->encoder.objectID; args.v5.ucEncoderMode = display_get_encoder_mode(connectorIndex); args.v5.ucPpll = pll->id; break; case 6: args.v6.ulDispEngClkFreq = B_HOST_TO_LENDIAN_INT32(crtcID << 24 | pll->pixelClock / 10); args.v6.ucRefDiv = pll->referenceDiv; args.v6.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v6.ulFbDivDecFrac = B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000); args.v6.ucPostDiv = pll->postDiv; args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ if (pll->ssPercentage > 0 && (pll->ssType & ATOM_EXTERNAL_SS_MASK) != 0) { args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; } switch (bitsPerColor) { case 8: default: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; break; case 10: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; break; case 12: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; break; case 16: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; break; } args.v6.ucTransmitterID = gConnector[connectorIndex]->encoder.objectID; args.v6.ucEncoderMode = display_get_encoder_mode(connectorIndex); args.v6.ucPpll = pll->id; break; default: TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8 " TODO\n", __func__, tableMajor, tableMinor); return B_ERROR; } TRACE("%s: set adjusted pixel clock %" B_PRIu32 " (was %" B_PRIu32 ")\n", __func__, pll->pixelClock, mode->timing.pixel_clock); status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args); if (ssEnabled) display_crtc_ss(pll, ATOM_ENABLE); return result; }
static inline void UMWriteInt32(uint8 * ptr, uint32 val) {*((uint32 *)ptr) = B_HOST_TO_LENDIAN_INT32(val);}
void VideoProducer::NodeRegistered() { if (fInitStatus != B_OK) { ReportError(B_NODE_IN_DISTRESS); return; } /* Set up the parameter web */ //TODO: remove and put sensible stuff there BParameterWeb *web = new BParameterWeb(); BParameterGroup *main = web->MakeGroup(Name()); BParameterGroup *g; /* g = main->MakeGroup("Color"); BDiscreteParameter *state = g->MakeDiscreteParameter( P_COLOR, B_MEDIA_RAW_VIDEO, "Color", "Color"); state->AddItem(B_HOST_TO_LENDIAN_INT32(0x00ff0000), "Red"); state->AddItem(B_HOST_TO_LENDIAN_INT32(0x0000ff00), "Green"); state->AddItem(B_HOST_TO_LENDIAN_INT32(0x000000ff), "Blue"); */ BParameter *p; g = main->MakeGroup("Info"); p = g->MakeTextParameter( P_INFO, B_MEDIA_RAW_VIDEO, "", "Info", 256); int32 id = P_LAST; if (fCamDevice) { #ifndef SINGLE_PARAMETER_GROUP main = web->MakeGroup("Device"); #endif fCamDevice->AddParameters(main, id); if (fCamDevice->Sensor()) { #ifndef SINGLE_PARAMETER_GROUP main = web->MakeGroup("Sensor"); #endif fCamDevice->Sensor()->AddParameters(main, id); } } fColor = B_HOST_TO_LENDIAN_INT32(0x00ff0000); fLastColorChange = system_time(); /* After this call, the BControllable owns the BParameterWeb object and * will delete it for you */ SetParameterWeb(web); fOutput.node = Node(); fOutput.source.port = ControlPort(); fOutput.source.id = 0; fOutput.destination = media_destination::null; strcpy(fOutput.name, Name()); /* Tailor these for the output of your device */ fOutput.format.type = B_MEDIA_RAW_VIDEO; fOutput.format.u.raw_video = media_raw_video_format::wildcard; fOutput.format.u.raw_video.interlace = 1; fOutput.format.u.raw_video.display.format = B_RGB32; fOutput.format.u.raw_video.field_rate = FIELD_RATE; // XXX: mmu /* Start the BMediaEventLooper control loop running */ Run(); }
status_t pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID) { uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; pll_info *pll = &gConnector[connectorIndex]->encoder.pll; pll->pixelClock = pixelClock; pll->id = pllID; pll_setup_flags(pll, crtcID); // set up any special flags pll_adjust(pll, crtcID); // get any needed clock adjustments, set reference/post dividers pll_compute(pll); // compute dividers int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); union set_pixel_clock args; memset(&args, 0, sizeof(args)); uint8 tableMajor; uint8 tableMinor; atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor); uint32 bitsPerChannel = 8; // TODO: Digital Depth, EDID 1.4+ on digital displays // isn't in Haiku edid common code? switch (tableMinor) { case 1: args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v1.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv); args.v1.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v1.ucFracFbDiv = pll->feedbackDivFrac; args.v1.ucPostDiv = pll->postDiv; args.v1.ucPpll = pll->id; args.v1.ucCRTC = crtcID; args.v1.ucRefDivSrc = 1; break; case 2: args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v2.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv); args.v2.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v2.ucFracFbDiv = pll->feedbackDivFrac; args.v2.ucPostDiv = pll->postDiv; args.v2.ucPpll = pll->id; args.v2.ucCRTC = crtcID; args.v2.ucRefDivSrc = 1; break; case 3: args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v3.usRefDiv = B_HOST_TO_LENDIAN_INT16(pll->referenceDiv); args.v3.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v3.ucFracFbDiv = pll->feedbackDivFrac; args.v3.ucPostDiv = pll->postDiv; args.v3.ucPpll = pll->id; args.v3.ucMiscInfo = (pll->id << 2); // if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) // args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; args.v3.ucTransmitterId = gConnector[connectorIndex]->encoder.objectID; args.v3.ucEncoderMode = display_get_encoder_mode(connectorIndex); break; case 5: args.v5.ucCRTC = crtcID; args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(pll->pixelClock / 10); args.v5.ucRefDiv = pll->referenceDiv; args.v5.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v5.ulFbDivDecFrac = B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000); args.v5.ucPostDiv = pll->postDiv; args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ // if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) // args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC; switch (bitsPerChannel) { case 8: default: args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; break; case 10: args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; break; } args.v5.ucTransmitterID = gConnector[connectorIndex]->encoder.objectID; args.v5.ucEncoderMode = display_get_encoder_mode(connectorIndex); args.v5.ucPpll = pllID; break; case 6: args.v6.ulDispEngClkFreq = B_HOST_TO_LENDIAN_INT32(crtcID << 24 | pll->pixelClock / 10); args.v6.ucRefDiv = pll->referenceDiv; args.v6.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedbackDiv); args.v6.ulFbDivDecFrac = B_HOST_TO_LENDIAN_INT32(pll->feedbackDivFrac * 100000); args.v6.ucPostDiv = pll->postDiv; args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ // if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) // args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; switch (bitsPerChannel) { case 8: default: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; break; case 10: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; break; case 12: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; break; case 16: args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; break; } args.v6.ucTransmitterID = gConnector[connectorIndex]->encoder.objectID; args.v6.ucEncoderMode = display_get_encoder_mode(connectorIndex); args.v6.ucPpll = pllID; break; default: TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8 " TODO\n", __func__, tableMajor, tableMinor); return B_ERROR; } TRACE("%s: set adjusted pixel clock %" B_PRIu32 " (was %" B_PRIu32 ")\n", __func__, pll->pixelClock, pixelClock); return atom_execute_table(gAtomContext, index, (uint32*)&args); }
status_t pll_external_set(uint32 clock) { TRACE("%s: set external pll clock to %" B_PRIu32 "\n", __func__, clock); if (clock == 0) ERROR("%s: Warning: default display clock is 0?\n", __func__); // also known as PLL display engineering uint8 tableMajor; uint8 tableMinor; int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor); TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor); union setPixelClock { SET_PIXEL_CLOCK_PS_ALLOCATION base; PIXEL_CLOCK_PARAMETERS v1; PIXEL_CLOCK_PARAMETERS_V2 v2; PIXEL_CLOCK_PARAMETERS_V3 v3; PIXEL_CLOCK_PARAMETERS_V5 v5; PIXEL_CLOCK_PARAMETERS_V6 v6; }; union setPixelClock args; memset(&args, 0, sizeof(args)); radeon_shared_info &info = *gInfo->shared_info; uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor; switch (tableMajor) { case 1: switch(tableMinor) { case 5: // If the default DC PLL clock is specified, // SetPixelClock provides the dividers. args.v5.ucCRTC = ATOM_CRTC_INVALID; args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(clock / 10); args.v5.ucPpll = ATOM_DCPLL; break; case 6: // If the default DC PLL clock is specified, // SetPixelClock provides the dividers. args.v6.ulDispEngClkFreq = B_HOST_TO_LENDIAN_INT32(clock / 10); if (dceVersion == 601) args.v6.ucPpll = ATOM_EXT_PLL1; else if (dceVersion >= 600) args.v6.ucPpll = ATOM_PPLL0; else args.v6.ucPpll = ATOM_DCPLL; break; default: ERROR("%s: Unknown table version %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor); } break; default: ERROR("%s: Unknown table version %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor); } return B_OK; }
static uint32 FlattenMMessageField(const MMessageField * f, void * outBuf) { /* 3. Entry name length (4 bytes) */ /* 4. Entry name string (flattened String) */ /* 5. Entry type code (4 bytes) */ /* 6. Entry data length (4 bytes) */ /* 7. Entry data (n bytes) */ /* Write entry name length */ uint32 writeOffset = 0; uint8 * buffer = (uint8 *) outBuf; { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(f->nameBytes); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write entry name */ memcpy(&buffer[writeOffset], f->name, f->nameBytes); writeOffset += f->nameBytes; /* Write entry type code */ { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(f->typeCode); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write entry data length */ { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(GetMMessageFieldFlattenedSize(f, MFalse)); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write entry data */ if (IsTypeCodeVariableSize(f->typeCode)) { uint32 numItems = f->numItems; uint32 i; if (f->typeCode == B_MESSAGE_TYPE) { /* Note that NULL entries will be flattened as empty Messages, since the protocol doesn't support them directly. */ /* Note also that for this type the number-of-items-in-array field is NOT written into the buffer (sigh) */ const MMessage ** msgs = (const MMessage **) f->data; for (i=0; i<numItems; i++) { const MMessage * subMsg = msgs[i]; uint32 msgSize = subMsg ? MMGetFlattenedSize(subMsg) : (3*sizeof(uint32)); uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(msgSize); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); if (subMsg) { MMFlattenMessage(subMsg, &buffer[writeOffset]); writeOffset += msgSize; } else { /* No MMessage present? Then we're going to have to fake one */ /* Format: 0. Protocol revision number (4 bytes, always set to CURRENT_PROTOCOL_VERSION) */ /* 1. 'what' code (4 bytes) */ /* 2. Number of entries (4 bytes) */ /* Write current protocol version */ uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(CURRENT_PROTOCOL_VERSION); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); /* Write 'what' code (zero) */ networkByteOrder = B_HOST_TO_LENDIAN_INT32(0); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); /* Write number of entries (zero) */ networkByteOrder = B_HOST_TO_LENDIAN_INT32(0); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } } } else { const MByteBuffer ** bufs = (const MByteBuffer **) f->data; int i; /* Write the number of items in the array */ uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(numItems); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); for (i=0; i<numItems; i++) { uint32 bufSize = bufs[i] ? bufs[i]->numBytes : 0; uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(bufSize); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); memcpy(&buffer[writeOffset], &bufs[i]->bytes, bufSize); writeOffset += bufSize; } } } else { uint32 dataSize = f->numItems*f->itemSize; MBool doMemcpy = MTrue; if (BYTE_ORDER != LITTLE_ENDIAN) { doMemcpy = MFalse; switch(f->typeCode) { case B_BOOL_TYPE: case B_INT8_TYPE: doMemcpy = MTrue; break; case B_POINT_TYPE: SwapCopy(&buffer[writeOffset], f->data, f->numItems*2, sizeof(float)); break; case B_RECT_TYPE: SwapCopy(&buffer[writeOffset], f->data, f->numItems*4, sizeof(float)); break; default: SwapCopy(&buffer[writeOffset], f->data, f->numItems, f->itemSize); break; } } if (doMemcpy) memcpy(&buffer[writeOffset], f->data, dataSize); writeOffset += dataSize; } return writeOffset; }
status_t Initialize(int fatbits, const char *device, const char *label, bool noprompt, bool testmode) { if (fatbits != 0 && fatbits != 12 && fatbits != 16 && fatbits != 32) { fprintf(stderr,"Error: don't know how to create a %d bit fat\n",fatbits); return B_ERROR; } //XXX the following two checks can be removed when this is fixed: #ifndef WITH_FLOPPY_SUPPORT if (0 != strstr(device,"floppy")) { fprintf(stderr,"Error: floppy B_GET_GEOMETRY and B_GET_BIOS_GEOMETRY calls are broken, floppy not supported\n"); return B_ERROR; } if (fatbits == 12) { fprintf(stderr,"Error: can't create a 12 bit fat on a device other than floppy\n"); return B_ERROR; } #endif printf("device = %s\n",device); int fd = open(device, O_RDWR); if (fd < 0) { fprintf(stderr, "Error: couldn't open file for device %s (%s)\n", device, strerror(errno)); return B_ERROR; } bool isRawDevice; bool hasBiosGeometry; bool hasDeviceGeometry; bool hasPartitionInfo; device_geometry biosGeometry; device_geometry deviceGeometry; partition_info partitionInfo; isRawDevice = 0 != strstr(device, "/raw"); hasBiosGeometry = B_OK == ioctl(fd, B_GET_BIOS_GEOMETRY, &biosGeometry, sizeof(biosGeometry)); hasDeviceGeometry = B_OK == ioctl(fd, B_GET_GEOMETRY, &deviceGeometry, sizeof(deviceGeometry)); hasPartitionInfo = B_OK == ioctl(fd, B_GET_PARTITION_INFO, &partitionInfo, sizeof(partitionInfo)); if (!isRawDevice && !hasBiosGeometry && !hasDeviceGeometry && !hasPartitionInfo) isRawDevice = true; if (hasBiosGeometry) { printf("bios geometry: %ld heads, %ld cylinders, %ld sectors/track, %ld bytes/sector\n", biosGeometry.head_count,biosGeometry.cylinder_count,biosGeometry.sectors_per_track,biosGeometry.bytes_per_sector); } if (hasBiosGeometry) { printf("device geometry: %ld heads, %ld cylinders, %ld sectors/track, %ld bytes/sector\n", deviceGeometry.head_count,deviceGeometry.cylinder_count,deviceGeometry.sectors_per_track,deviceGeometry.bytes_per_sector); } if (hasPartitionInfo) { printf("partition info: start at %Ld bytes (%Ld sectors), %Ld KB, %Ld MB, %Ld GB\n", partitionInfo.offset, partitionInfo.offset / 512, partitionInfo.offset / 1024, partitionInfo.offset / (1024 * 1024), partitionInfo.offset / (1024 * 1024 * 1024)); printf("partition info: size %Ld bytes, %Ld KB, %Ld MB, %Ld GB\n", partitionInfo.size, partitionInfo.size / 1024, partitionInfo.size / (1024 * 1024), partitionInfo.size / (1024 * 1024 * 1024)); } if (!isRawDevice && !hasPartitionInfo) { fprintf(stderr,"Warning: couldn't get partition information\n"); } if ((hasBiosGeometry && biosGeometry.bytes_per_sector != 512) || (hasDeviceGeometry && deviceGeometry.bytes_per_sector != 512)) { fprintf(stderr,"Error: geometry block size not 512 bytes\n"); close(fd); return B_ERROR; } else if (hasPartitionInfo && partitionInfo.logical_block_size != 512) { printf("partition logical block size is not 512, it's %ld bytes\n", partitionInfo.logical_block_size); } if (hasDeviceGeometry && deviceGeometry.read_only) { fprintf(stderr,"Error: this is a read-only device\n"); close(fd); return B_ERROR; } if (hasDeviceGeometry && deviceGeometry.write_once) { fprintf(stderr,"Error: this is a write-once device\n"); close(fd); return B_ERROR; } uint64 size = 0; if (hasPartitionInfo) { size = partitionInfo.size; } else if (hasDeviceGeometry) { size = uint64(deviceGeometry.bytes_per_sector) * deviceGeometry.sectors_per_track * deviceGeometry.cylinder_count * deviceGeometry.head_count; } else if (hasBiosGeometry) { size = uint64(biosGeometry.bytes_per_sector) * biosGeometry.sectors_per_track * biosGeometry.cylinder_count * biosGeometry.head_count; } else { // maybe it's just a file struct stat stat; if (fstat(fd, &stat) < 0) { fprintf(stderr, "Error: couldn't get device partition or geometry information, nor size\n"); close(fd); return B_ERROR; } size = stat.st_size; } // TODO still valid on Haiku ? /*if (isRawDevice && size > FLOPPY_MAX_SIZE) { fprintf(stderr,"Error: device too large for floppy, or raw devices not supported\n"); close(fd); return B_ERROR; }*/ printf("size = %Ld bytes (%Ld sectors), %Ld KB, %Ld MB, %Ld GB\n", size, size / 512, size / 1024, size / (1024 * 1024), size / (1024 * 1024 * 1024)); if (fatbits == 0) { //auto determine fat type if (isRawDevice && size <= FLOPPY_MAX_SIZE && (size / FAT12_CLUSTER_MAX_SIZE) < FAT12_MAX_CLUSTER_COUNT) { fatbits = 12; } else if ((size / CLUSTER_MAX_SIZE) < FAT16_MAX_CLUSTER_COUNT) { fatbits = 16; } else if ((size / CLUSTER_MAX_SIZE) < FAT32_MAX_CLUSTER_COUNT) { fatbits = 32; } } if (fatbits == 0) { fprintf(stderr,"Error: device too large for 32 bit fat\n"); close(fd); return B_ERROR; } int sectorPerCluster; sectorPerCluster = 0; if (fatbits == 12) { sectorPerCluster = 0; if (size <= 4182016LL) sectorPerCluster = 2; // XXX don't know the correct value if (size <= 2091008LL) sectorPerCluster = 1; // XXX don't know the correct value } else if (fatbits == 16) { // special BAD_CLUSTER value is 0xFFF7, // but this should work anyway, since space required by // two FATs will make maximum cluster count smaller. // at least, this is what I think *should* happen sectorPerCluster = 0; //larger than 2 GB must fail if (size <= (2048 * 1024 * 1024LL)) // up to 2GB, use 32k clusters sectorPerCluster = 64; if (size <= (1024 * 1024 * 1024LL)) // up to 1GB, use 16k clusters sectorPerCluster = 32; if (size <= (512 * 1024 * 1024LL)) // up to 512MB, use 8k clusters sectorPerCluster = 16; if (size <= (256 * 1024 * 1024LL)) // up to 256MB, use 4k clusters sectorPerCluster = 8; if (size <= (128 * 1024 * 1024LL)) // up to 128MB, use 2k clusters sectorPerCluster = 4; if (size <= (16 * 1024 * 1024LL)) // up to 16MB, use 2k clusters sectorPerCluster = 2; if (size <= 4182016LL) // smaller than fat32 must fail sectorPerCluster = 0; } if (fatbits == 32) { sectorPerCluster = 64; // default is 32k clusters if (size <= (32 * 1024 * 1024 * 1024LL)) // up to 32GB, use 16k clusters sectorPerCluster = 32; if (size <= (16 * 1024 * 1024 * 1024LL)) // up to 16GB, use 8k clusters sectorPerCluster = 16; if (size <= (8 * 1024 * 1024 * 1024LL)) // up to 8GB, use 4k clusters sectorPerCluster = 8; if (size <= (532480 * 512LL)) // up to 260 MB, use 0.5k clusters sectorPerCluster = 1; if (size <= (66600 * 512LL)) // smaller than 32.5 MB must fail sectorPerCluster = 0; } if (sectorPerCluster == 0) { fprintf(stderr,"Error: failed to determine sector per cluster value, partition too large for %d bit fat\n",fatbits); close(fd); return B_ERROR; } int reservedSectorCount = 0; // avoid compiler warning int rootEntryCount = 0; // avoid compiler warning int numFATs; int sectorSize; uint8 biosDriveId; // get bios drive-id, or use 0x80 if (B_OK != ioctl(fd, B_GET_BIOS_DRIVE_ID, &biosDriveId, sizeof(biosDriveId))) { biosDriveId = 0x80; } else { printf("bios drive id: 0x%02x\n", (int)biosDriveId); } // default parameters for the bootsector numFATs = 2; sectorSize = 512; if (fatbits == 12 || fatbits == 16) reservedSectorCount = 1; if (fatbits == 32) reservedSectorCount = 32; if (fatbits == 12) rootEntryCount = 128; // XXX don't know the correct value if (fatbits == 16) rootEntryCount = 512; if (fatbits == 32) rootEntryCount = 0; // Determine FATSize // calculation done as MS recommends uint64 dskSize = size / sectorSize; uint32 rootDirSectors = ((rootEntryCount * 32) + (sectorSize - 1)) / sectorSize; uint64 tmpVal1 = dskSize - (reservedSectorCount + rootDirSectors); uint64 tmpVal2 = (256 * sectorPerCluster) + numFATs; if (fatbits == 32) tmpVal2 = tmpVal2 / 2; uint32 FATSize = (tmpVal1 + (tmpVal2 - 1)) / tmpVal2; // FATSize should now contain the size of *one* FAT, measured in sectors // RootDirSectors should now contain the size of the fat12/16 root directory, measured in sectors printf("fatbits = %d, clustersize = %d\n", fatbits, sectorPerCluster * 512); printf("FAT size is %ld sectors\n", FATSize); printf("disk label: %s\n", label); char bootsector[512]; memset(bootsector,0x00,512); memcpy(bootsector + BOOTJMP_START_OFFSET, bootjmp, sizeof(bootjmp)); memcpy(bootsector + BOOTCODE_START_OFFSET, bootcode, sizeof(bootcode)); if (fatbits == 32) { bootsector32 *bs = (bootsector32 *)bootsector; uint16 temp16; uint32 temp32; memcpy(bs->BS_OEMName,"Haiku ",8); bs->BPB_BytsPerSec = B_HOST_TO_LENDIAN_INT16(sectorSize); bs->BPB_SecPerClus = sectorPerCluster; bs->BPB_RsvdSecCnt = B_HOST_TO_LENDIAN_INT16(reservedSectorCount); bs->BPB_NumFATs = numFATs; bs->BPB_RootEntCnt = B_HOST_TO_LENDIAN_INT16(rootEntryCount); bs->BPB_TotSec16 = B_HOST_TO_LENDIAN_INT16(0); bs->BPB_Media = 0xF8; bs->BPB_FATSz16 = B_HOST_TO_LENDIAN_INT16(0); temp16 = hasBiosGeometry ? biosGeometry.sectors_per_track : 63; bs->BPB_SecPerTrk = B_HOST_TO_LENDIAN_INT16(temp16); temp16 = hasBiosGeometry ? biosGeometry.head_count : 255; bs->BPB_NumHeads = B_HOST_TO_LENDIAN_INT16(temp16); temp32 = hasPartitionInfo ? (partitionInfo.size / 512) : 0; bs->BPB_HiddSec = B_HOST_TO_LENDIAN_INT32(temp32); temp32 = size / 512; bs->BPB_TotSec32 = B_HOST_TO_LENDIAN_INT32(temp32); bs->BPB_FATSz32 = B_HOST_TO_LENDIAN_INT32(FATSize); bs->BPB_ExtFlags = B_HOST_TO_LENDIAN_INT16(0); bs->BPB_FSVer = B_HOST_TO_LENDIAN_INT16(0); bs->BPB_RootClus = B_HOST_TO_LENDIAN_INT32(FAT32_ROOT_CLUSTER); bs->BPB_FSInfo = B_HOST_TO_LENDIAN_INT16(FSINFO_SECTOR_NUM); bs->BPB_BkBootSec = B_HOST_TO_LENDIAN_INT16(BACKUP_SECTOR_NUM); memset(bs->BPB_Reserved,0,12); bs->BS_DrvNum = biosDriveId; bs->BS_Reserved1 = 0x00; bs->BS_BootSig = 0x29; *(uint32*)bs->BS_VolID = (uint32)system_time(); memcpy(bs->BS_VolLab,"NO NAME ",11); memcpy(bs->BS_FilSysType,"FAT32 ",8); bs->signature = B_HOST_TO_LENDIAN_INT16(0xAA55); } else { bootsector1216 *bs = (bootsector1216 *)bootsector; uint16 temp16; uint32 temp32; uint32 sectorcount = size / 512; memcpy(bs->BS_OEMName, "Haiku ", 8); bs->BPB_BytsPerSec = B_HOST_TO_LENDIAN_INT16(sectorSize); bs->BPB_SecPerClus = sectorPerCluster; bs->BPB_RsvdSecCnt = B_HOST_TO_LENDIAN_INT16(reservedSectorCount); bs->BPB_NumFATs = numFATs; bs->BPB_RootEntCnt = B_HOST_TO_LENDIAN_INT16(rootEntryCount); temp16 = (sectorcount <= 65535) ? sectorcount : 0; bs->BPB_TotSec16 = B_HOST_TO_LENDIAN_INT16(temp16); bs->BPB_Media = 0xF8; bs->BPB_FATSz16 = B_HOST_TO_LENDIAN_INT16(FATSize); temp16 = hasBiosGeometry ? biosGeometry.sectors_per_track : 63; bs->BPB_SecPerTrk = B_HOST_TO_LENDIAN_INT16(temp16); temp16 = hasBiosGeometry ? biosGeometry.head_count : 255; bs->BPB_NumHeads = B_HOST_TO_LENDIAN_INT16(temp16); temp32 = hasPartitionInfo ? (partitionInfo.size / 512) : 0; bs->BPB_HiddSec = B_HOST_TO_LENDIAN_INT32(temp32); temp32 = (sectorcount <= 65535) ? 0 : sectorcount; bs->BPB_TotSec32 = B_HOST_TO_LENDIAN_INT32(temp32); bs->BS_DrvNum = biosDriveId; bs->BS_Reserved1 = 0x00; bs->BS_BootSig = 0x29; *(uint32*)bs->BS_VolID = (uint32)system_time(); memcpy(bs->BS_VolLab,"NO NAME ",11); memcpy(bs->BS_FilSysType,(fatbits == 12) ? "FAT12 " : "FAT16 ",8); bs->signature = B_HOST_TO_LENDIAN_INT16(0xAA55); } if (!noprompt) { printf("\n"); printf("Initializing will erase all existing data on the drive.\n"); printf("Do you wish to proceed? "); char answer[1000]; char *p; memset(answer, 0, 1000); fflush(stdout); p = fgets(answer, 1000, stdin); if (p && (p=strchr(p, '\n'))) *p = '\0'; /* remove newline */ if ((p == NULL) || (strlen(answer) < 1) || (0 != strncasecmp(answer, "yes", strlen(answer)))) { printf("drive NOT initialized\n"); close(fd); return B_OK; } } if (testmode) { close(fd); return B_OK; } // Disk layout: // 0) reserved sectors, this includes the bootsector, fsinfosector and bootsector backup // 1) FAT // 2) root directory (not on fat32) // 3) file & directory data ssize_t written; // initialize everything with zero first // avoid doing 512 byte writes here, they are slow printf("Writing FAT\n"); char * zerobuffer = (char *)malloc(65536); memset(zerobuffer,0,65536); int64 bytes_to_write = 512LL * (reservedSectorCount + (numFATs * FATSize) + rootDirSectors); int64 pos = 0; while (bytes_to_write > 0) { ssize_t writesize = min_c(bytes_to_write, 65536); written = write_pos(fd, pos, zerobuffer, writesize); if (written != writesize) { fprintf(stderr,"Error: write error near sector %Ld\n",pos / 512); close(fd); return B_ERROR; } bytes_to_write -= writesize; pos += writesize; } free(zerobuffer); //write boot sector printf("Writing boot block\n"); written = write_pos(fd, BOOT_SECTOR_NUM * 512, bootsector, 512); if (written != 512) { fprintf(stderr,"Error: write error at sector %d\n", BOOT_SECTOR_NUM); close(fd); return B_ERROR; } if (fatbits == 32) { written = write_pos(fd, BACKUP_SECTOR_NUM * 512, bootsector, 512); if (written != 512) { fprintf(stderr,"Error: write error at sector %d\n", BACKUP_SECTOR_NUM); close(fd); return B_ERROR; } } //write first fat sector printf("Writing first FAT sector\n"); uint8 sec[512]; memset(sec,0,512); if (fatbits == 12) { //FAT[0] contains media byte in lower 8 bits, all other bits set to 1 //FAT[1] contains EOF marker sec[0] = 0xF8; sec[1] = 0xFF; sec[2] = 0xFF; } else if (fatbits == 16) { //FAT[0] contains media byte in lower 8 bits, all other bits set to 1 sec[0] = 0xF8; sec[1] = 0xFF; //FAT[1] contains EOF marker sec[2] = 0xFF; sec[3] = 0xFF; } else if (fatbits == 32) { //FAT[0] contains media byte in lower 8 bits, all other bits set to 1 sec[0] = 0xF8; sec[1] = 0xFF; sec[2] = 0xFF; sec[3] = 0xFF; //FAT[1] contains EOF marker sec[4] = 0xFF; sec[5] = 0xFF; sec[6] = 0xFF; sec[7] = 0x0F; //FAT[2] contains EOF marker, used to terminate root directory sec[8] = 0xFF; sec[9] = 0xFF; sec[10] = 0xFF; sec[11] = 0x0F; } written = write_pos(fd, reservedSectorCount * 512, sec, 512); if (written != 512) { fprintf(stderr,"Error: write error at sector %d\n", reservedSectorCount); close(fd); return B_ERROR; } if (numFATs > 1) { written = write_pos(fd, (reservedSectorCount + FATSize) * 512,sec,512); if (written != 512) { fprintf(stderr,"Error: write error at sector %ld\n", reservedSectorCount + FATSize); close(fd); return B_ERROR; } } //write fsinfo sector if (fatbits == 32) { printf("Writing boot info\n"); //calculate total sector count first uint64 free_count = size / 512; //now account for already by metadata used sectors free_count -= reservedSectorCount + (numFATs * FATSize) + rootDirSectors; //convert from sector to clustercount free_count /= sectorPerCluster; //and account for 1 already used cluster of root directory free_count -= 1; fsinfosector32 fsinfosector; memset(&fsinfosector,0x00,512); fsinfosector.FSI_LeadSig = B_HOST_TO_LENDIAN_INT32(0x41615252); fsinfosector.FSI_StrucSig = B_HOST_TO_LENDIAN_INT32(0x61417272); fsinfosector.FSI_Free_Count = B_HOST_TO_LENDIAN_INT32((uint32)free_count); fsinfosector.FSI_Nxt_Free = B_HOST_TO_LENDIAN_INT32(3); fsinfosector.FSI_TrailSig = B_HOST_TO_LENDIAN_INT32(0xAA550000); written = write_pos(fd, FSINFO_SECTOR_NUM * 512, &fsinfosector, 512); if (written != 512) { fprintf(stderr,"Error: write error at sector %d\n", FSINFO_SECTOR_NUM); close(fd); return B_ERROR; } } //write volume label into root directory printf("Writing root directory\n"); if (fatbits == 12 || fatbits == 16) { uint8 data[512]; memset(data, 0, 512); CreateVolumeLabel(data, label); uint32 rootDirSector = reservedSectorCount + (numFATs * FATSize); written = write_pos(fd, rootDirSector * 512, data, 512); if (written != 512) { fprintf(stderr,"Error: write error at sector %ld\n", rootDirSector); close(fd); return B_ERROR; } } else if (fatbits == 32) { int size = 512 * sectorPerCluster; uint8 *cluster = (uint8*)malloc(size); memset(cluster, 0, size); CreateVolumeLabel(cluster, label); uint32 rootDirSector = reservedSectorCount + (numFATs * FATSize) + rootDirSectors; written = write_pos(fd, rootDirSector * 512, cluster, size); free(cluster); if (written != size) { fprintf(stderr,"Error: write error at sector %ld\n", rootDirSector); close(fd); return B_ERROR; } } ioctl(fd, B_FLUSH_DRIVE_CACHE); close(fd); return B_OK; }
// main int main(int argc, const char *const *argv) { kArgc = argc; kArgv = argv; if (argc < 2) print_usage_and_exit(true); // parameters const char **files = new const char*[argc]; int fileCount = 0; bool dryRun = false; off_t startOffset = 0; // parse arguments for (int argi = 1; argi < argc;) { const char *arg = argv[argi++]; if (arg[0] == '-') { if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { print_usage_and_exit(false); } else if (strcmp(arg, "--dry-run") == 0) { dryRun = true; } else if (strcmp(arg, "-alert") == 0) { // ignore } else if (strcmp(arg, "-full") == 0) { // ignore } else if (strcmp(arg, "--start-offset") == 0) { if (argi >= argc) print_usage_and_exit(true); startOffset = strtoll(argv[argi++], NULL, 0); } else if (strcmp(arg, "-safe") == 0) { fprintf(stderr, "Error: Sorry, BeOS R3 isn't supported!\n"); exit(1); } else { print_usage_and_exit(true); } } else { files[fileCount++] = arg; } } // we need at least one file if (fileCount == 0) print_usage_and_exit(true); // read the boot code uint8 *bootCodeData = NULL; #ifndef __ANTARES__ bootCodeData = read_boot_code_data(argv[0]); #else image_info info; if (find_own_image(&info) == B_OK) bootCodeData = read_boot_code_data(info.name); #endif if (!bootCodeData) { fprintf(stderr, "Error: Failed to read \n"); exit(1); } // iterate through the files and make them bootable status_t error; for (int i = 0; i < fileCount; i++) { const char *fileName = files[i]; BEntry entry; error = entry.SetTo(fileName, true); if (error != B_OK) { fprintf(stderr, "Error: Failed to open \"%s\": %s\n", fileName, strerror(error)); exit(1); } // get stat to check the type of the file struct stat st; error = entry.GetStat(&st); if (error != B_OK) { fprintf(stderr, "Error: Failed to stat \"%s\": %s\n", fileName, strerror(error)); exit(1); } bool noPartition = false; int64 partitionOffset = 0; fs_info info; // needs to be here (we use the device name later) if (S_ISDIR(st.st_mode)) { #if defined(__BEOS__) || defined(__ANTARES__) // a directory: get the device error = fs_stat_dev(st.st_dev, &info); if (error != B_OK) { fprintf(stderr, "Error: Failed to determine device for " "\"%s\": %s\n", fileName, strerror(error)); exit(1); } fileName = info.device_name; #else (void)info; fprintf(stderr, "Error: Specifying directories not supported " "on this platform!\n"); exit(1); #endif } else if (S_ISREG(st.st_mode)) { // a regular file: fine noPartition = true; } else if (S_ISCHR(st.st_mode)) { // character special: a device or partition under BeOS // or under FreeBSD #if !(defined(__BEOS__) || defined(__ANTARES__)) && !defined(ANTARES_HOST_PLATFORM_FREEBSD) fprintf(stderr, "Error: Character special devices not " "supported on this platform.\n"); exit(1); #endif #ifdef ANTARES_HOST_PLATFORM_FREEBSD // chop off the trailing number int fileNameLen = strlen(fileName); int baseNameLen = -1; for (int k = fileNameLen - 1; k >= 0; k--) { if (!isdigit(fileName[k])) { baseNameLen = k + 1; break; } } // Remove de 's' from 'ad2s2' slice device (partition for DOS // users) to get 'ad2' base device baseNameLen--; if (baseNameLen < 0) { // only digits? fprintf(stderr, "Error: Failed to get base device name.\n"); exit(1); } if (baseNameLen < fileNameLen) { // get base device name and partition index char baseDeviceName[B_PATH_NAME_LENGTH]; int partitionIndex = atoi(fileName + baseNameLen + 1); // Don't forget the 's' of slice :) memcpy(baseDeviceName, fileName, baseNameLen); baseDeviceName[baseNameLen] = '\0'; // open base device int baseFD = open(baseDeviceName, O_RDONLY); if (baseFD < 0) { fprintf(stderr, "Error: Failed to open \"%s\": %s\n", baseDeviceName, strerror(errno)); exit(1); } // get device size int64 deviceSize; if (ioctl(baseFD, DIOCGMEDIASIZE, &deviceSize) == -1) { fprintf(stderr, "Error: Failed to get device geometry " "for \"%s\": %s\n", baseDeviceName, strerror(errno)); exit(1); } // parse the partition map // TODO: block size! PartitionMapParser parser(baseFD, 0, deviceSize, 512); PartitionMap map; error = parser.Parse(NULL, &map); if (error != B_OK) { fprintf(stderr, "Error: Parsing partition table on " "device \"%s\" failed: %s\n", baseDeviceName, strerror(error)); exit(1); } close(baseFD); // check the partition we are supposed to write at Partition *partition = map.PartitionAt(partitionIndex - 1); if (!partition || partition->IsEmpty()) { fprintf(stderr, "Error: Invalid partition index %d.\n", partitionIndex); dump_partition_map(map); exit(1); } if (partition->IsExtended()) { fprintf(stderr, "Error: Partition %d is an extended " "partition.\n", partitionIndex); dump_partition_map(map); exit(1); } partitionOffset = partition->Offset(); } else { // The given device is the base device. We'll write at // offset 0. } #endif // ANTARES_HOST_PLATFORM_FREEBSD } else if (S_ISBLK(st.st_mode)) { // block device: a device or partition under Linux or Darwin #ifdef ANTARES_HOST_PLATFORM_LINUX // chop off the trailing number int fileNameLen = strlen(fileName); int baseNameLen = -1; for (int k = fileNameLen - 1; k >= 0; k--) { if (!isdigit(fileName[k])) { baseNameLen = k + 1; break; } } if (baseNameLen < 0) { // only digits? fprintf(stderr, "Error: Failed to get base device name.\n"); exit(1); } if (baseNameLen < fileNameLen) { // get base device name and partition index char baseDeviceName[B_PATH_NAME_LENGTH]; int partitionIndex = atoi(fileName + baseNameLen); memcpy(baseDeviceName, fileName, baseNameLen); baseDeviceName[baseNameLen] = '\0'; // open base device int baseFD = open(baseDeviceName, O_RDONLY); if (baseFD < 0) { fprintf(stderr, "Error: Failed to open \"%s\": %s\n", baseDeviceName, strerror(errno)); exit(1); } // get device size -- try BLKGETSIZE64, but, if it doesn't // work, fall back to the obsolete HDIO_GETGEO int64 deviceSize; hd_geometry geometry; if (ioctl(baseFD, BLKGETSIZE64, &deviceSize) == 0 && deviceSize > 0) { // looks good } else if (ioctl(baseFD, HDIO_GETGEO, &geometry) == 0) { deviceSize = (int64)geometry.heads * geometry.sectors * geometry.cylinders * 512; } else { fprintf(stderr, "Error: Failed to get device geometry " "for \"%s\": %s\n", baseDeviceName, strerror(errno)); exit(1); } // parse the partition map // TODO: block size! PartitionMapParser parser(baseFD, 0, deviceSize, 512); PartitionMap map; error = parser.Parse(NULL, &map); if (error != B_OK) { fprintf(stderr, "Error: Parsing partition table on " "device \"%s\" failed: %s\n", baseDeviceName, strerror(error)); exit(1); } close(baseFD); // check the partition we are supposed to write at Partition *partition = map.PartitionAt(partitionIndex - 1); if (!partition || partition->IsEmpty()) { fprintf(stderr, "Error: Invalid partition index %d.\n", partitionIndex); dump_partition_map(map); exit(1); } if (partition->IsExtended()) { fprintf(stderr, "Error: Partition %d is an extended " "partition.\n", partitionIndex); dump_partition_map(map); exit(1); } partitionOffset = partition->Offset(); } else { // The given device is the base device. We'll write at // offset 0. } #elif defined(ANTARES_HOST_PLATFORM_DARWIN) // chop off the trailing number int fileNameLen = strlen(fileName); int baseNameLen = fileNameLen - 2; // get base device name and partition index char baseDeviceName[B_PATH_NAME_LENGTH]; int partitionIndex = atoi(fileName + baseNameLen + 1); memcpy(baseDeviceName, fileName, baseNameLen); baseDeviceName[baseNameLen] = '\0'; // open base device int baseFD = open(baseDeviceName, O_RDONLY); if (baseFD < 0) { fprintf(stderr, "Error: Failed to open \"%s\": %s\n", baseDeviceName, strerror(errno)); exit(1); } // get device size int64 blockSize; int64 blockCount; int64 deviceSize; if (ioctl(baseFD, DKIOCGETBLOCKSIZE, &blockSize) == -1) { fprintf(stderr, "Error: Failed to get block size " "for \"%s\": %s\n", baseDeviceName, strerror(errno)); exit(1); } if (ioctl(baseFD, DKIOCGETBLOCKCOUNT, &blockCount) == -1) { fprintf(stderr, "Error: Failed to get block count " "for \"%s\": %s\n", baseDeviceName, strerror(errno)); exit(1); } deviceSize = blockSize * blockCount; // parse the partition map PartitionMapParser parser(baseFD, 0, deviceSize, blockSize); PartitionMap map; error = parser.Parse(NULL, &map); if (error != B_OK) { fprintf(stderr, "Error: Parsing partition table on " "device \"%s\" failed: %s\n", baseDeviceName, strerror(error)); exit(1); } close(baseFD); // check the partition we are supposed to write at Partition *partition = map.PartitionAt(partitionIndex - 1); if (!partition || partition->IsEmpty()) { fprintf(stderr, "Error: Invalid partition index %d.\n", partitionIndex); dump_partition_map(map); exit(1); } if (partition->IsExtended()) { fprintf(stderr, "Error: Partition %d is an extended " "partition.\n", partitionIndex); dump_partition_map(map); exit(1); } partitionOffset = partition->Offset(); #else // partitions are block devices under Antares, but not under BeOS #ifndef __ANTARES__ fprintf(stderr, "Error: Block devices not supported on this " "platform!\n"); exit(1); #endif // __ANTARES__ #endif } else { fprintf(stderr, "Error: File type of \"%s\" is not supported.\n", fileName); exit(1); } // open the file int fd = open(fileName, O_RDWR); if (fd < 0) { fprintf(stderr, "Error: Failed to open \"%s\": %s\n", fileName, strerror(errno)); exit(1); } #if (defined(__BEOS__) || defined(__ANTARES__)) // get a partition info if (!noPartition && strlen(fileName) >= 3 && strncmp("raw", fileName + strlen(fileName) - 3, 3)) { partition_info partitionInfo; if (ioctl(fd, B_GET_PARTITION_INFO, &partitionInfo, sizeof(partitionInfo)) == 0) { partitionOffset = partitionInfo.offset; } else { fprintf(stderr, "Error: Failed to get partition info: %s\n", strerror(errno)); exit(1); } } #endif // __BEOS__ // adjust the partition offset in the boot code data // hard coded sector size: 512 bytes *(uint32*)(bootCodeData + kPartitionOffsetOffset) = B_HOST_TO_LENDIAN_INT32((uint32)(partitionOffset / 512)); // write the boot code printf("Writing boot code to \"%s\" (partition offset: %" B_PRId64 " bytes, start offset = %" B_PRIdOFF ") " "...\n", fileName, partitionOffset, startOffset); write_boot_code_part(fileName, fd, startOffset, bootCodeData, 0, kFirstBootCodePartSize, dryRun); write_boot_code_part(fileName, fd, startOffset, bootCodeData, kSecondBootCodePartOffset, kSecondBootCodePartSize, dryRun); #ifdef __ANTARES__ // check if this partition is mounted BDiskDeviceRoster roster; BPartition* partition; BDiskDevice device; status_t status = roster.GetPartitionForPath(fileName, &device, &partition); if (status != B_OK) { status = roster.GetFileDeviceForPath(fileName, &device); if (status == B_OK) partition = &device; } if (status == B_OK && partition->IsMounted() && !dryRun) { // This partition is mounted, we need to tell BFS to update its // boot block (we are using part of the same logical block). BPath path; status = partition->GetMountPoint(&path); if (status == B_OK) { update_boot_block update; update.offset = kSecondBootCodePartOffset - 512; update.data = bootCodeData + kSecondBootCodePartOffset; update.length = kSecondBootCodePartSize; int mountFD = open(path.Path(), O_RDONLY); if (ioctl(mountFD, BFS_IOCTL_UPDATE_BOOT_BLOCK, &update, sizeof(update_boot_block)) != 0) { fprintf(stderr, "Could not update BFS boot block: %s\n", strerror(errno)); } close(mountFD); } else { fprintf(stderr, "Could not update BFS boot code while the " "partition is mounted!\n"); } } #endif // __ANTARES__ close(fd); } return 0; }