; ; Copyright (c) 2012, RISC OS Open Ltd ; Copyright (c) 2012, Adrian Lees ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are met: ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; * Neither the name of RISC OS Open Ltd nor the names of its contributors ; may be used to endorse or promote products derived from this software ; without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE ; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ; POSSIBILITY OF SUCH DAMAGE. ; ; With many thanks to Broadcom Europe Ltd for releasing the source code to ; its Linux drivers, thus making this port possible. ; AREA |!!!ROMStart|, CODE, READONLY, PIC GET Hdr:ListOpts GET Hdr:Macros GET Hdr:System GET Hdr:Machine. GET Hdr:HALSize. GET Hdr:FSNumbers GET Hdr:NewErrors GET Hdr:BCMSupport GET Hdr:HALEntries GET hdr.BCM2835 GET hdr.StaticWS GET hdr.CastleMacros IMPORT Interrupt_Init IMPORT HAL_IRQEnable IMPORT HAL_IRQDisable IMPORT HAL_IRQClear IMPORT HAL_IRQSource IMPORT HAL_IRQStatus IMPORT HAL_FIQEnable IMPORT HAL_FIQDisable IMPORT HAL_FIQDisableAll IMPORT HAL_FIQClear IMPORT HAL_FIQSource IMPORT HAL_FIQStatus IMPORT HAL_IRQMax IMPORT Timer_Init IMPORT HAL_Timers IMPORT HAL_TimerDevice IMPORT HAL_TimerGranularity IMPORT HAL_TimerMaxPeriod IMPORT HAL_TimerSetPeriod IMPORT HAL_TimerPeriod IMPORT HAL_TimerReadCountdown IMPORT HAL_TimerIRQClear IMPORT HAL_CounterRate IMPORT HAL_CounterPeriod IMPORT HAL_CounterRead IMPORT HAL_CounterDelay IMPORT IIC_Init IMPORT HAL_IICBuses IMPORT HAL_IICType IMPORT HAL_IICTransfer IMPORT HAL_IICMonitorTransfer IMPORT HAL_NVMemoryType IMPORT HAL_NVMemorySize IMPORT HAL_NVMemoryPageSize IMPORT HAL_NVMemoryProtectedSize IMPORT HAL_NVMemoryProtection IMPORT HAL_NVMemoryRead IMPORT HAL_NVMemoryWrite IMPORT HAL_UARTPorts IMPORT HAL_UARTStartUp IMPORT HAL_UARTShutdown IMPORT HAL_UARTFeatures IMPORT HAL_UARTReceiveByte IMPORT HAL_UARTTransmitByte IMPORT HAL_UARTLineStatus IMPORT HAL_UARTInterruptEnable IMPORT HAL_UARTRate IMPORT HAL_UARTFormat IMPORT HAL_UARTFIFOSize IMPORT HAL_UARTFIFOClear IMPORT HAL_UARTFIFOEnable IMPORT HAL_UARTFIFOThreshold IMPORT HAL_UARTInterruptID IMPORT HAL_UARTBreak IMPORT HAL_UARTModemControl IMPORT HAL_UARTModemStatus IMPORT HAL_UARTDevice IMPORT HAL_UARTDefault [ Debug IMPORT HAL_DebugRX IMPORT HAL_DebugTX ] IMPORT HAL_PlatformName IMPORT HAL_KbdScanSetup IMPORT HAL_KbdScan IMPORT HAL_KbdScanFinish IMPORT HAL_KbdScanInterrupt IMPORT HAL_USBControllerInfo IMPORT SDIO_InitDevices IMPORT DMA_InitDevices IMPORT GPIO_InitDevices IMPORT VCHIQ_InitDevices IMPORT Video_InitDevices IMPORT RTC_InitDevices IMPORT SPI_InitDevices IMPORT Touch_InitDevices IMPORT BCMMBox_InitDevices IMPORT HAL_SendHostMessage IMPORT HAL_QueryPlatform IMPORT GetVCBuffer EXPORT HAL_Base IMPORT memcpy [ HALDebug EXPORT HAL_DebugHexTX4 EXPORT HAL_DebugTXStrInline ] EXPORT reset EXPORT workspace ENTRY HAL_Base reset B start undef B undefined_instr swi B swi_instr pabort B prefetch_abort dabort B data_abort irq B interrupt fiq B fast_interrupt ; exception handlers just for use during HAL init, ; in case something goes wrong undefined_instr B . swi_instr B . prefetch_abort B . data_abort B . interrupt B . fast_interrupt B . ALIGN 256 atags ; list of 'atags' structures constructed here by the loader code ; running on VideoCore, describing ; - available memory ; - command line parameters, including framebuffer parameters ALIGN 4096 end_stack workspace % sizeof_workspace ALIGN 32768 ASSERT . - HAL_Base = 32768 start MRC p15, 0, lr, c0, c0, 0 ; read Main ID Register AND lr, lr, #&FF00 CMP lr, #&C000 ; xxxxB76x for ARM1176, xxxxC07x for Cortex-A7 BCC %F02 ; no MPIDR or HYP mode in ARM1176 ; Sometimes a secondary CPU gets here (indicates a bug somewhere) ; Prevent it doing any further damage if so MRC p15, 0, lr, c0, c0, 5 ; read MPIDR TST lr, #&FF 01 WFINE BNE %BT01 ; Some versions of the firmware call us in HYP mode, which requires ; a secret handshake to drop into SVC mode MRS lr, CPSR AND lr, lr, #M32_bits TEQ lr, #HYP32_mode BNE %F02 ADR lr, %F03 MSR SPSR_cxsf, #F32_bit+I32_bit+SVC32_mode MSR SPSR_x, #A32_bit MSR elr_hyp, lr ERET 02 MSR CPSR_c,#F32_bit+I32_bit+SVC32_mode 03 ADRL v1, HAL_Base + OSROM_HALSize ; v1 -> RISC OS image LDR v8, [v1, #OSHdr_Entries] ADD v8, v8, v1 ; v8 -> RISC OS entry table ; Ensure CPU is 'set up' (typically enables ICache) MOV a1, #0 CallOSM OS_InitARM ADRL sb,workspace ADRL R13,end_stack ADRL r4, reset STR r4, MMUOffBaseAddr MRC p15,0,r4,c0,c0,0 ; read Main ID Register AND r4,r4,#&FF00 CMP r4,#&C000 ; xxxxB76x for ARM1176, xxxxC07x for Cortex-A7 LDRCC r4,=IO_Base_BCM2835 LDRCS r4,=IO_Base_BCM2836 STR r4,PeriBase [ HALDebug mov a1, #1 bl HAL_UARTStartUp ; start early for debug use bl HAL_DebugTXStrInline DCB "HalStartup",10,0 ALIGN ] [ JTAG ; Configure the GPIO pins used for JTAG LDR a1, PeriBase ADD a1, a1, #GPIO_Base LDR a2, [a1, #GPFSel2] LDR a3, =&3f00003f AND a2, a2, a3 ; Keep settings for 20, 21, 28, 29 LDR a3, =(3<<6)+(3<<9)+(3<<12)+(3<<15)+(3<<18)+(3<<21) ; Set 22-27 to alt4 ORR a2, a2, a3 STR a2, [a1, #GPFSel2] ] ; Enable USB power ; Note - may need changing to enable other devices in future ; Looks like we need to write the logical OR of all the devices we want enabled MOV r1, #0 LDR r0,=(16:SHL:MB_Pwr_USB)+MB_Chan_Pwr BL HAL_SendHostMessage ; From config.txt we might have loaded some CMOS settings above the ROM, ; import those into our workspace (they may subsequently turn out to be junk) ADRL a1, HAL_Base + OSROM_HALSize LDR a3, [a1, #OSHdr_ImageSize] ADD a2, a3, a1 ; loaded immediately after OS image ADR a1, SimulatedCMOS LDR a3, =?SimulatedCMOS BL memcpy ; Query the platform BL HAL_QueryPlatform [ HALDebug bl HAL_DebugTXStrInline DCB "HalStartup2",10,0 ALIGN ] LDR v3, ARM_Base LDR v4, ARM_Size [ HALDebug ADRL a1, reset BL HAL_DebugHexTX4 MOV a1, v3 BL HAL_DebugHexTX4 MOV a1, v4 BL HAL_DebugHexTX4 BL HAL_DebugTXStrInline DCB "ROM start, RAM start, RAM size", 10, 0 ALIGN ] relocate_code ; Relocate ROM to high end of RAM ADRL v1, HAL_Base + OSROM_HALSize LDR v2, [v1, #OSHdr_ImageSize] LDR lr, [v1, #OSHdr_Flags] TST lr, #OSHdrFlag_SupportsCompression LDRNE lr, [v1, #OSHdr_CompressedSize] MOVEQ lr, v2 SUB v1, v1, #OSROM_HALSize ; Start of HAL ADD v2, v2, #OSROM_HALSize ; Size of HAL+OS ADD lr, lr, #OSROM_HALSize ; Size of compressed HAL+OS ADD v5, v1, lr ; End of OS ADD v7, v3, v4 ; End of RAM SUB ip, v7, v2 ; New start address of HAL CMP v1, ip BEQ relocate_10 ; No copy needed CMP v1, v7 BHI relocate_20 ; We're in some ROM above RAM. OK to continue with copy. CMP v5, ip BLS relocate_20 ; We're in some ROM/RAM below our copy destination. OK to continue with copy. ; Else we currently overlap the area we want to copy ourselves into. SUB ip, v1, lr ; Copy the HAL+OS to just before itself. relocate_20 MOV a1, ip ; Copy dest MOV a2, v1 ; Copy source MOV a3, lr ; Copy length relocate_30 LDR a4, [a2], #4 SUBS a3, a3, #4 STR a4, [a1], #4 BGT relocate_30 MOV a1, #0 MCR p15, 0, a1, c7, c10, 4 ; drain write buffer MCR p15, 0, a1, c7, c5, 0 ; invalidate I-Cache ; Jump to our new copy ADR a1, relocate_code SUB a2, ip, v1 ADD a1, a1, a2 ; relocate our branch target ADD v8, v8, a2 ; Update OS entry table ptr MOV pc, a1 relocate_10 ; Copy completed, reset stack & workspace ptrs ADD sp, v3, #4096 ; Use RAM for stack instead of bits of ROM ADRL sb, workspace ; However workspace is still in ROM :( [ HALDebug BL HAL_DebugTXStrInline DCB "ROM relocated", 10, 0 ALIGN ] ; If we're a multi-core chip, the other cores should be sat in a boot ; stub located at &0, waiting for us to give them the address of some ; code to execute. Move them into a holding space in the relocated ROM ; so that we don't break them when we overwrite the boot stub. MRC p15, 0, lr, c0, c0, 0 ; read Main ID Register AND lr, lr, #&FF00 CMP lr, #&C000 ; xxxxB76x for ARM1176, xxxxC07x for Cortex-A7 BCC clear_ram LDR a1, =QA7_BASE MVN a2, #0 STR a2, [a1, #QA7_CORE0_MBOX1_RDCLR] ; Clear our mailboxes STR a2, [a1, #QA7_CORE0_MBOX2_RDCLR] STR a2, [a1, #QA7_CORE0_MBOX3_RDCLR] DSB ADR a2, holding_pattern STR a2, [a1, #QA7_CORE1_MBOX3_SET] ; Each core is sat waiting for mailbox 3 STR a2, [a1, #QA7_CORE2_MBOX3_SET] STR a2, [a1, #QA7_CORE3_MBOX3_SET] DSB SEV ; Current boot stub just has the cores in a spin loop, but use SEV just in case future stubs are more power-conscious ; Now wait for the cores to acknowledge the request (input via our mailboxes) MOV a3, #1<<20 ; Timeout MOV a4, #QA7_CORE0_MBOX1_RDCLR 10 SUBS a3, a3, #1 BEQ %FT20 LDR a2, [a1, a4] CMP a2, #0 BEQ %BT10 CMP a4, #QA7_CORE0_MBOX3_RDCLR ADDNE a4, a4, #QA7_CORE0_MBOX2_RDCLR-QA7_CORE0_MBOX1_RDCLR BNE %BT10 [ HALDebug BL HAL_DebugTXStrInline DCB "Aux cores in holding pattern", 10, 0 ALIGN B %FT25 ] 20 [ HALDebug BL HAL_DebugTXStrInline DCB "Failed waking cores", 10, 0 ALIGN 25 ] clear_ram ; Clear RAM ; v3 is start of RAM ; ip is end of RAM/start of ROM ; Note this code will clear the stack, but there shouldn't be anything on it yet anyway MOV a1, ip MOV a2, #0 MOV a3, #0 MOV a4, #0 MOV v1, #0 MOV v4, #0 MOV v5, #0 MOV v7, #0 MOV lr, #0 clear_lp1 STMDB a1!,{a2-a4,v1,v4,v5,v7,lr} STMDB a1!,{a2-a4,v1,v4,v5,v7,lr} STMDB a1!,{a2-a4,v1,v4,v5,v7,lr} STMDB a1!,{a2-a4,v1,v4,v5,v7,lr} CMP a1, v3 BHI clear_lp1 MOV a2, v3 MOV a3, ip [ HALDebug BL HAL_DebugTXStrInline DCB "HalStartup3 .. rst rend",10,0 ALIGN MOV a1, a2 BL HAL_DebugHexTX4 MOV a1, a3 BL HAL_DebugHexTX4 ] MVN a4, #0 MOV a1, #0 STR a1, [sp, #-4]! ;reference handle (NULL for first call) CallOSM OS_AddRAM STR a1,[sp] ;ref for next call ; OS kernel informed of RAM areas LDR a2, PeriBase ADD a2, a2, #PM_Base LDR a2, [a2, #PM_RSTS] ; consider reset status TST a2, #PM_RSTS_HADPOR LDR a4,[sp],#4 ;!!! ref from last AddRAM MOV a1, #OSStartFlag_RAMCleared ORRNE a1, a1, #OSStartFlag_POR ADRL a2, HAL_Base + OSROM_HALSize ; a2 -> RISC OS image ADR a3, HALdescriptor CallOSM OS_Start ; OS_Start doesn't return....invokes HAL_Init after MMU activation holding_pattern ; Auxilliary cores arrive here ; First, work out who we are MRC p15, 0, a1, c0, c0, 5 ; Read MPIDR AND a1, a1, #3 ; Extract core number (should be 1-3) [ HALDebug DSB LDR a2, =IO_Base_BCM2836+UART_Base ADD a3, a1, #'0' STRB a3, [a2, #UARTDR] ] DSB ; Clear our mailbox register LDR a2, =QA7_BASE ADD a3, a2, #QA7_CORE0_MBOX0_SET ADD a3, a3, a1, LSL #2 ; Box to reply to core 0 on ADD a4, a2, #QA7_CORE0_MBOX3_RDCLR ADD a4, a4, a1, LSL #4 ; Box to receive instructions via MVN v1, #0 STR v1, [a4] DSB ; Let the master core know that we're here STR pc, [a3] ; Any non-zero should do ; Now wait for further instruction 10 WFE LDR v1, [a4] CMP v1, #0 BEQ %BT10 [ HALDebug DSB LDR a2, =IO_Base_BCM2836+UART_Base ADD a3, a1, #'0' STRB a3, [a2, #UARTDR] ] ADR lr, holding_pattern ; Allow return to the holding pattern to simplify testing BX v1 LTORG HALdescriptor DATA DCD HALFlag_NCNBWorkspace DCD HAL_Base - HALdescriptor DCD OSROM_HALSize DCD HAL_EntryTable - HALdescriptor DCD HAL_Entries DCD sizeof_workspace HAL_EntryTable DATA HALEntry HAL_Init HALEntry HAL_IRQEnable HALEntry HAL_IRQDisable HALEntry HAL_IRQClear HALEntry HAL_IRQSource HALEntry HAL_IRQStatus HALEntry HAL_FIQEnable HALEntry HAL_FIQDisable HALEntry HAL_FIQDisableAll HALEntry HAL_FIQClear HALEntry HAL_FIQSource HALEntry HAL_FIQStatus HALEntry HAL_Timers HALEntry HAL_TimerDevice HALEntry HAL_TimerGranularity HALEntry HAL_TimerMaxPeriod HALEntry HAL_TimerSetPeriod HALEntry HAL_TimerPeriod HALEntry HAL_TimerReadCountdown HALEntry HAL_CounterRate HALEntry HAL_CounterPeriod HALEntry HAL_CounterRead HALEntry HAL_CounterDelay HALEntry HAL_NVMemoryType HALEntry HAL_NVMemorySize HALEntry HAL_NVMemoryPageSize HALEntry HAL_NVMemoryProtectedSize HALEntry HAL_NVMemoryProtection NullEntry ; HAL_NVMemoryIICAddress HALEntry HAL_NVMemoryRead HALEntry HAL_NVMemoryWrite HALEntry HAL_IICBuses HALEntry HAL_IICType NullEntry ; HAL_IICSetLines NullEntry ; HAL_IICReadLines NullEntry ; HAL_IICDevice HALEntry HAL_IICTransfer HALEntry HAL_IICMonitorTransfer NullEntry ; HAL_VideoFlybackDevice NullEntry ; HAL_VideoSetMode NullEntry ; HAL_VideoWritePaletteEntry NullEntry ; HAL_VideoWritePaletteEntries NullEntry ; HAL_VideoReadPaletteEntry NullEntry ; HAL_VideoSetInterlace NullEntry ; HAL_VideoSetBlank NullEntry ; HAL_VideoSetPowerSave NullEntry ; HAL_VideoUpdatePointer NullEntry ; HAL_VideoSetDAG NullEntry ; HAL_VideoVetMode NullEntry ; HAL_VideoPixelFormats NullEntry ; HAL_VideoFeatures NullEntry ; HAL_VideoBufferAlignment NullEntry ; HAL_VideoOutputFormat NullEntry ; HALEntry HAL_MatrixColumns NullEntry ; HALEntry HAL_MatrixScan NullEntry ; HALEntry HAL_TouchscreenType NullEntry ; HALEntry HAL_TouchscreenRead NullEntry ; HALEntry HAL_TouchscreenMode NullEntry ; HALEntry HAL_TouchscreenMeasure HALEntry HAL_MachineID HALEntry HAL_ControllerAddress HALEntry HAL_HardwareInfo HALEntry HAL_SuperIOInfo HALEntry HAL_PlatformInfo NullEntry ; HALEntry HAL_CleanerSpace HALEntry HAL_UARTPorts HALEntry HAL_UARTStartUp HALEntry HAL_UARTShutdown HALEntry HAL_UARTFeatures HALEntry HAL_UARTReceiveByte HALEntry HAL_UARTTransmitByte HALEntry HAL_UARTLineStatus HALEntry HAL_UARTInterruptEnable HALEntry HAL_UARTRate HALEntry HAL_UARTFormat HALEntry HAL_UARTFIFOSize HALEntry HAL_UARTFIFOClear HALEntry HAL_UARTFIFOEnable HALEntry HAL_UARTFIFOThreshold HALEntry HAL_UARTInterruptID HALEntry HAL_UARTBreak HALEntry HAL_UARTModemControl HALEntry HAL_UARTModemStatus HALEntry HAL_UARTDevice HALEntry HAL_Reset [ Debug HALEntry HAL_DebugRX HALEntry HAL_DebugTX | NullEntry ; HAL_DebugRX NullEntry ; HAL_DebugTX ] NullEntry ; HAL_PCIFeatures NullEntry ; HAL_PCIReadConfigByte NullEntry ; HAL_PCIReadConfigHalfword NullEntry ; HAL_PCIReadConfigWord NullEntry ; HAL_PCIWriteConfigByte NullEntry ; HAL_PCIWriteConfigHalfword NullEntry ; HAL_PCIWriteConfigWord NullEntry ; HAL_PCISpecialCycle NullEntry ; HAL_PCISlotTable NullEntry ; HAL_PCIAddresses HALEntry HAL_PlatformName NullEntry NullEntry HALEntry HAL_InitDevices HALEntry HAL_KbdScanSetup HALEntry HAL_KbdScan HALEntry HAL_KbdScanFinish HALEntry HAL_KbdScanInterrupt HALEntry HAL_PhysInfo HALEntry HAL_USBControllerInfo HALEntry HAL_IRQMax NullEntry ; HALEntry HAL_VideoRender NullEntry ; HAL_USBPortPower NullEntry ; HAL_USBPortStatus NullEntry ; HAL_USBPortDevice NullEntry ; HALEntry HAL_VideoIICOp HALEntry HAL_TimerIRQClear NullEntry ; HAL_TimerIRQStatus HALEntry HAL_ExtMachineID NullEntry ; HALEntry HAL_VideoFramestoreAddress HALEntry HAL_UARTDefault NullEntry ; HALEntry HAL_VideoStartupMode HAL_Entries * (.-HAL_EntryTable)/4 ;-------------------------------------------------------------------------------------- ; HAL Initialisation callback from OS kernel ;-------------------------------------------------------------------------------------- HAL_Init Push "v5, lr" MOV v5, a2 BL SetUpOSEntries MOV a1, #0 ; map in the IO space MRC p15, 0, a2, c0, c0, 0 ; read Main ID Register AND a2, a2, #&FF00 CMP a2, #&C000 ; xxxxB76x for ARM1176, xxxxC07x for Cortex-A7 LDRCC a2, =IO_Base_BCM2835 LDRCS a2, =IO_Base_BCM2836 LDR a3, =IO_Size CallOS OS_MapInIO STR a1, PeriBase [ Debug MOV a1,#0 ; start the uart ..we use it for debug BL HAL_UARTStartUp ; restart to capture logical io address [ HALDebug bl HAL_DebugTXStrInline DCB "HalStart from OS",10,0 ALIGN ] ] ; Recover various values that are now trapped in ROM from when the workspace ; and ROM overlapped prior to relocation. Copy them into RW memory at sb. ADRL a4, workspace ; where they are post ROM relocation LDR a1, [a4, #:INDEX:FB_CacheMode] STR a1, FB_CacheMode ; GPU cache mode LDR a3, [a4, #:INDEX:VC_Size] LDR a2, [a4, #:INDEX:VC_Base] LDR a1, [a4, #:INDEX:ARM_Base] LDR ip, [a4, #:INDEX:ARM_Size] STR a3, VC_Size STR a2, VC_Base STR a1, ARM_Base STR ip, ARM_Size LDR a3, [a4, #:INDEX:Board_Model] LDR a2, [a4, #:INDEX:Board_Revision] LDR a1, [a4, #:INDEX:ARM_DMAChannels] LDR ip, [a4, #:INDEX:SafetyCatch] STR a3, Board_Model STR a2, Board_Revision STR a1, ARM_DMAChannels STR ip, SafetyCatch [ HALDebug LDR a1, VC_Base BL HAL_DebugHexTX4 LDR a1, VC_Size BL HAL_DebugHexTX4 BL HAL_DebugTXStrInline DCB "VC memory",10,0 ALIGN ] ; Get the physical address of NCNB workspace ; v5 -> start of NCNB workspace STR v5, NCNBAddr MOV a1, v5 CallOS OS_LogToPhys LDR a3, FB_CacheMode ORR a1, a1, a3 STR a1, NCNBPhysAddr ; Try and initialise virtual GPIO buffer LDR a1, =ARM2VC_Tag_GetVirtGPIOBuf MOV a2, #4096 ; should only need a word, but request a whole page for safety (avoid getting caught out if they make the buffer bigger in future) LDR a3, =ARM2VC_Tag_SetVirtGPIOBuf BL GetVCBuffer STR a1, VirtGPIOBuf BL CMOS_Init BL Interrupt_Init ; initialise our interrupts BL Timer_Init BL IIC_Init [ HALDebug BL HAL_DebugTXStrInline DCB "HAL Init completed",10,0 ALIGN ] Pull "v5, pc" ; Initialise the simulated CMOS. CMOS_Init ROUT Push "v1, lr" ADRL a1, workspace ; where it got relocated to ADD v1, a1, #:INDEX:SimulatedCMOS LDR a4, [v1, #?SimulatedCMOS - 4] SUB a4, a4, #500 ; Check version word is from RISC OS 5 CMP a4, #100 BHS %FT10 ; Now we need to take the logical CMOS file order and make it physical ; The resulting layout from logical is [F0-FF][C0-EF][00-BF][100-END] ADR a1, SimulatedCMOS ADD a2, v1, #&F0 MOV a3, #16*1 BL memcpy ADD a1, a1, #16*1 ADD a2, v1, #&C0 MOV a3, #16*3 BL memcpy ADD a1, a1, #16*3 ADD a2, v1, #0 MOV a3, #16*12 BL memcpy ADD a1, a1, #16*12 ADD a2, v1, #&100 MOV a3, #?SimulatedCMOS - 4 - &100 BL memcpy Pull "v1, pc" 10 ADR a1, SimulatedCMOS MOV a2, #-1 ; Zap it to a known blank state LDR a3, =?SimulatedCMOS - 4 20 STR a2, [a1, a3] SUBS a3, a3, #4 BPL %BT20 Pull "v1, pc" ; Initialise and relocate the entry table. SetUpOSEntries ROUT STR a1, OSheader LDR a2, [a1, #OSHdr_NumEntries] CMP a2, #HighestOSEntry+1 MOVHI a2, #HighestOSEntry+1 ADRL a3, OSentries LDR a4, [a1, #OSHdr_Entries] ADD a4, a4, a1 05 SUBS a2, a2, #1 LDR ip, [a4, a2, LSL #2] ADD ip, ip, a4 STR ip, [a3, a2, LSL #2] BNE %BT05 MOV pc, lr HAL_ControllerAddress MOV a1, #0 MOV pc, lr HAL_HardwareInfo LDR ip, =&FFFFFF00 STR ip, [a1] MOV ip, #0 STR ip, [a2] LDR ip, =&00FFFF00 STR ip, [a3] MOV pc, lr HAL_PlatformInfo MOV ip, #2_10000 ; no podules,no PCI cards,no multi CPU,no soft off,and soft ROM STR ip, [a2] MOV ip, #2_11111 ; mask of valid bits STR ip, [a3] MOV pc, lr HAL_SuperIOInfo MOV ip, #0 STR ip, [a1] STR ip, [a2] MOV pc, lr HAL_MachineID ; ADR ip, MachAD LDR ip, MachAD LDMIA ip, {a1, a2} mov pc, lr MachAD DCD :INDEX:workspace + :INDEX:MachineID HAL_ExtMachineID MOVS ip, a1 MOV a1, #0 MOV pc, lr HAL_Reset MRS a1, CPSR ORR a1, a1, #I32_bit+F32_bit ; paranoia, don't allow reset to be interrupted MSR CPSR_c, a1 LDR a1, PeriBase ADD a1, a1, #PM_Base DoMemBarrier a3 LDR a2, [a1, #PM_RSTC] MOV a3, #PM_Password BIC a2, a2, #PM_RSTC_WRCFG_MASK ORR a2, a2, #PM_RSTC_WRCFG_FULLRST ORR a2, a2, a3 ADD a3, a3, #10 STR a3, [a1, #PM_WDOG] STR a2, [a1, #PM_RSTC] B . HAL_PhysInfo ROUT TEQ a1, #PhysInfo_GetTableSize MOVEQ a1, #524288 ; Two pages in each byte, so (2^32)/(4096*2) STREQ a1, [a2] MVNEQ a1, #0 MOVEQ pc, lr TEQ a1, #PhysInfo_HardROM MOVEQ a1, #0 ; No hard ROM MOVEQ a2, #0 STMEQIA a3, {a1-a2} MVNEQ a1, #0 MOVEQ pc, lr TEQ a1, #PhysInfo_WriteTable MOVNE a1, #0 MOVNE pc, lr Push "v1-v5,lr" LDR v1, ARM_Base LDR v2, ARM_Size ADD v2, v1, v2 STMIA a3, {v1-v2} ; All RAM the OS knows about will be here ; Majority of table is unused, so prefill it LDR v3, =&88888888 ; Unused regions (or RAM) MOV a1, v3 MOV a3, v3 MOV a4, v3 ADD v4, a2, #524288 10 STMIA a2!, {a1,a3,a4,v3} CMP a2, v4 BLO %BT10 ; Fill in IO region MRC p15,0,v5,c0,c0,0 ; read Main ID Register AND v5,v5,#&FF00 CMP v5,#&C000 ; xxxxB76x for ARM1176, xxxxC07x for Cortex-A7 SUB a2, a2, #524288-(IO_Base_BCM2835>>13) ADDCS a2, a2, #(IO_Base_BCM2836-IO_Base_BCM2835)>>13 ORR a1, a1, a1, LSR #1 ; Pattern for IO regions ORR a3, a3, a3, LSR #1 ORR a4, a4, a4, LSR #1 ORR v3, v3, v3, LSR #1 ADD v5, a2, #IO_Size>>13 20 STMIA a2!, {a1,a3,a4,v3} CMP a2, v5 BLO %BT20 ; VC memory is effectively IO, so fill it in as such SUB a2, v4, #524288 LDR v1, VC_Base LDR v2, VC_Size ADD a2, a2, v1, LSR #13 ADD v5, a2, v2, LSR #13 30 STMIA a2!, {a1,a3,a4,v3} CMP a2, v5 BLO %BT30 MVN a1, #0 Pull "v1-v5,pc" HAL_Null MOV pc, lr HAL_InitDevices STR lr, [sp, #-4]! BL Video_InitDevices ; Must be before DMA_InitDevices BL SDIO_InitDevices BL DMA_InitDevices BL GPIO_InitDevices BL VCHIQ_InitDevices BL RTC_InitDevices BL SPI_InitDevices BL Touch_InitDevices BL BCMMBox_InitDevices LDR pc, [sp], #4 [ HALDebug ; a2-> null terminated string HAL_DebugTXS ROUT STMFD sp!, {a1-a4,v1,ip,lr} SUB v1, a2, #1 1 LDRB a1, [v1,#1]! TEQ a1, #&0 LDMEQFD sp!, {a1-a4,v1,ip,pc} BL HAL_DebugTX B %BT1 HAL_DebugHexTX stmfd r13!, {r0-r3,ip,lr} b jbdt1 HAL_DebugHexTX2 stmfd r13!, {r0-r3,ip,lr} b jbdt2 HAL_DebugHexTX4 stmfd r13!, {r0-r3,ip,lr} mov r0,r0,ror #24 ; hi byte bl jbdtxh mov r0,r0,ror #24 bl jbdtxh jbdt2 mov r0,r0,ror #24 bl jbdtxh mov r0,r0,ror #24 jbdt1 bl jbdtxh mov r0,#' ' bl HAL_DebugTX ldmfd r13!, {r0-r3,ip,pc} HAL_DebugTXStrInline stmfd r13!, {a1-a4,v1,ip} ; lr points to prinstring, immediately ; following call, null terminated sub v1,lr,#1 1 ldrb a1,[v1,#1]! ; pop next char, auto incr teq a1,#0 ; terminating null biceq lr,v1,#3 ; round down address ldmeqfd r13!,{a1-a4,v1,ip} addeq pc,lr,#4 ; return to next word bl HAL_DebugTX ; else send, then b %bt1 ; loop jbdtxh stmfd r13!,{a1-a4,v1,ip,lr} ; print byte as hex and v1,a1,#&f ; get low nibble and a1,a1,#&f0 ; get hi nibble mov a1,a1,lsr #4 ; shift to low nibble cmp a1,#&9 ; 9? addle a1,a1,#&30 addgt a1,a1,#&37 ; convert letter if needed bl HAL_DebugTX cmp v1,#9 addle a1,v1,#&30 addgt a1,v1,#&37 bl HAL_DebugTX ldmfd r13!,{a1-a4,v1,ip,pc} ] END