With RISC OS 5.19 the HAL specification was extended to add a generic method of creating self-extracting compressed ROM images. In order for a compressed image to operate correctly, both the HAL and the OS must be aware of the compression.
Currently, only a partial region of the OS image will be compressed. The HAL will remain uncompressed, and the uncompressed portion of the OS image is responsible for decompressing the image. This minimises the amount of changes that must be made to a HAL in order to add compression support. Although the OS is responsible for decompressing the image, the decompression code isn’t directly contained within the image itself. Instead the decompression code is contained in a stub which is located somewhere in the compressed region. This means the OS doesn’t need to be aware of the compression algorithm that’s in use, as well as avoiding bloating the uncompressed image with needless decompression code.
If the OS supports compression, the ‘supports compression’ flag in the OS image header must be set, and words 5-7 of the header must be valid. The value the ‘compression offset’ field gives the offset from the image header to the start of the compressed data. All data from that point up to the end of the image (as indicated by the ‘image size’ field) will potentially be compressed.
If an image is compressed, the value in the ‘compressed image size’ field must contain the size of the compressed image. This includes the size of the uncompressed portion of the OS image, the size of the compressed data, the size of the decompression stub, and the size of any additional data that forms part of the image (e.g. RISC OS ROM footer). This total must be less than the value of the ‘image size’ field. Compressed images must also set the ‘decompression header offset’ field to a valid value.
If an image is uncompressed, the ‘compressed image size’ field must be set to the same value as the ‘image size’ field, and the ‘decompression header offset’ must be set to zero.
Ordinarily, the decompression header will be located within the compressed region. This allows it to be removed from the image once the image has been decompressed.
Word 0: Decompression workspace size (bytes, multiple of 4K) Word 1: Offset from decompression header to decompression code
The decompression workspace size can be set to zero if no decompression workspace is required.
The decompression code must obey the ATPCS calling standards, as per the rest of the HAL/OS entry points. It is entered with the following parameters:
a1 - Pointer to OS image header a2 - Pointer to IMB function a3 - Pointer to decompression workspace (word aligned)
Currently there is no prescribed limit on the amount of stack space that the decompression routine may use. Within current RISC OS versions there will be at most 15KB of stack available, but it is recommended that decompression routines use as little stack space as possible.
The decompression workspace will have been zero-initialised by the OS.
The decompression code is expected to perform an in-place decompression of the compressed portion of the ROM image, and then patch up the OS header by setting the decompression header offset to zero and setting the compressed image size field to be identical to the image size field. The resulting image is expected to be an exact match for the original uncompressed image.
The IMB function should be used whenever an IMB operation is required, e.g. after copying the decompression stub to the workspace. It follows the ATPCS, and accepts the following parameters:
a1 - Flags: Bit 0 => If set, IMB range specified in a2,a3. Else perform full IMB. Bits 1-31 reserved a2 - First byte of IMB range (inclusive) a3 - Last byte of IMB range (inclusive)
(This is currently an exact match for the OS_SynchroniseCodeAreas SWI)
Note that it is not necessary to IMB the decompressed image once the decompression is complete; the OS will perform this action itself.
The HAL is required to ensure that any compressed image is located in a physically contiguous section of RAM large enough to hold the uncompressed image. When updating HALs to add support for compressed images, it may be necessary to update any code that deals with relocating the OS image in order to ensure that the ‘compressed image size’ field is used to calculate how much data should be copied, and not the ‘image size’ field.
With current kernel versions, the compression offset is set to the start of the module chain. This means the entire kernel is uncompressed. ROM decompression is performed during the startup keyboard scan; this will be after the MMU and caches are enabled, after RAM has been cleared (if the HAL hasn’t cleared it already), and after HAL_Init (and HAL_KbdScanSetup) has been called.
Although the specification dictates that the decompression workspace size must be a multiple of 4K, decompression workspace is currently allocated in 1MB chunks, to simplify the code required to free the workspace once decompression is complete.
The ‘rompress’ tool (castle.RiscOS.Tools.Sources.rompress) can be used to compress and decompress compatible RISC OS ROM images.