Newton Patches

General Mechanism

NewtonOS patches work by mapping ROM code to RAM via the Memory Management Unit (MMU). Mapping is done on a per page basis. Each page has a size of 4k. Patching a page requires placing a copy of the original code in the ROM into a patch page, and modifying the data to be patched.

More background information can be found here:

Patchable Areas

Since the NewtonOS ROMs can differ from model to model, certain areas of the ROMs have been fixed in their layout, and designated as patchable areas. The patchable areas usually contain jump tables, providing one level of indirection for function calls. This allows replacing function implementations easily, and helps reducing the number of pages which need to be remapped.

An important aspect of the patchable areas is that they are only sparsely populated: Only the first 128 bytes are usually used. As an example, the patchable area at 0x01a00000 only contains 32 patchable vectors:

0x01a00000 FIQHandler
0x01a00004 IRQHandler
0x01a00008 GenericSWIHandler
0x01a0000c __fp_decode
0x01a00010 PrefetchAbortHandler
0x01a00014 InterruptedSuperMode
0x01a00018 IsFIQMode
0x01a0001c LowLevelCopyEngine
0x01a00020 LowLevelCopyEngineLong
0x01a00024 MonitorEntryGlue
0x01a00028 AirusAL16__FUlP15AirusAParmBlock
0x01a0002c AirusAL__FUlP15AirusAParmBlock
0x01a00030 AL16_GetAttribute2__FUl
0x01a00034 AL16_GetAttribute__FUl
0x01a00038 AL16_NextSet__FP15AirusAParmBlock
0x01a0003c AL16_Shell__FiP15AirusAParmBlock
0x01a00040 AL16_Verify__FP15AirusAParmBlock
0x01a00044 AL_FilterString__FPc
0x01a00048 AL_GetAttribute2__FUl
0x01a0004c AL_GetAttribute__FUl
0x01a00050 AL_NextSet__FP15AirusAParmBlock
0x01a00054 AL_Shell__FUlP15AirusAParmBlock
0x01a00058 AL_Verify__FP15AirusAParmBlock
0x01a0005c Ashortstrcpy__FPUsT1
0x01a00060 Ashortstrlen__FPUs
0x01a00064 Astrchr__FPcc
0x01a00068 Astrcpy__FPcT1
0x01a0006c Astrlen__FPc
0x01a00070 CallAirusA
0x01a00074 ChangeAttribute
0x01a00078 DeleteWord
0x01a0007c DisposDictionary

This is important when looking at the MMU page table patch information: The patch information for the page tables only needs to cover the first 128 bytes of a 4k page, the rest of the page is not relevant. This reduces the size of the patches significantly.

Memory Layouts

A patch links together four different areas:

  1. The patchable areas in the ROM
  2. The MMU level 2 tables in RAM
  3. Patches to the MMU level 2 tables in the patch
  4. Patch code for the patchable areas in the patch

The links are:

  • MMU patch information to code in the path: The link is done via the LoadPage macro. It instructs the MMU which page in the patch to refer to. Pages in the patch are numbered 2 to 7 for the ROM patch, and there is one page (number 1) in the REx patch.
  • Patched code back to proper virtual address: The mapping of the patched code back into the virtual address space is done implicitly by using calculating the proper offset into the patch table, and using that in the updated code for the patchable area.

Patch pages are coded with position independent code: Mapping page 2 to address 0x01d80000 or to address 0x01da0000 results in the same content.

Anatomy of a Patch

To understand how a patch works in detail, the 717260 patch serves as a good example. The reverse engineered source code is located on SourceForge.

Creating own Patches

Here is a list of potential patches to be developed:

  • Empty Patch: Purpose is to clear out the MMU patch tables and get the Newton into an unpatched state
  • Minimum Patch: Purpose is to take the empty patch and patch just one function
  • Larger Patch: Purpose is to add a new page to the patch
  • New Page Patch: Purpose is to remap a new page of the pageable area
  • Changed Page Patch: Purpose is to change an existing patched page