Skip to content

Commit

Permalink
OcAppleKernelLib: Fix relocation support for EfiBoot in KC mode
Browse files Browse the repository at this point in the history
  • Loading branch information
vit9696 committed Jul 5, 2020
1 parent 1a71973 commit 2705377
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 7 deletions.
28 changes: 28 additions & 0 deletions Docs/Sample.plist
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,34 @@
<key>Skip</key>
<integer>0</integer>
</dict>
<dict>
<key>Base</key>
<string>_vstart</string>
<key>Comment</key>
<string>Print K and dead loop</string>
<key>Count</key>
<integer>1</integer>
<key>Enabled</key>
<false/>
<key>Find</key>
<data></data>
<key>Identifier</key>
<string>kernel</string>
<key>Limit</key>
<integer>0</integer>
<key>Mask</key>
<data></data>
<key>MaxKernel</key>
<string></string>
<key>MinKernel</key>
<string></string>
<key>Replace</key>
<data>sUtmuv0D7KggdPtmuvgDiMjusQpmuv0D7KggdPtmuvgDiMju6/6Q</data>
<key>ReplaceMask</key>
<data></data>
<key>Skip</key>
<integer>0</integer>
</dict>
</array>
<key>Quirks</key>
<dict>
Expand Down
40 changes: 39 additions & 1 deletion Library/OcAppleKernelLib/KernelCollection.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,44 @@ InternalKcWriteCommandHeaders (
//
MachHeader->NumCommands++;
MachHeader->CommandsSize += sizeof (MACH_SEGMENT_COMMAND_64);

//
// Proceed to the next command.
//
Command.Address += Command.FilesetEntry->CommandSize;

//
// Write new __PRELINKED_INFO segment, as the first writeable segment is used by EfiBoot
// as a relocation base. Relocation in KC mode is very simplified, and this segment PADDR
// is simply used for all the relocations in DYSYMTAB. Unless we leave it untouched, sliding
// will "relocate" invalid memory, as new plist is normally put at the end of KC memory.
//
// Note, that we might need to resolve Context->PrelinkedInfoSegment if regions move upper
// and current __PRELINKED_INFO gets shifted.
//
CopyMem (
(VOID *) Command.Address,
Context->PrelinkedInfoSegment,
Context->PrelinkedInfoSegment->CommandSize
);

//
// Must choose a different name to avoid collisions.
//
CopyMem (Context->PrelinkedInfoSegment->SegmentName, "__KREMLIN_START", sizeof ("__KREMLIN_START"));
CopyMem (Context->PrelinkedInfoSection->SectionName, "__kremlin_start", sizeof ("__kremlin_start"));

//
// Refresh Mach-O header constants to include the new segment command.
//
MachHeader->NumCommands++;
MachHeader->CommandsSize += Context->PrelinkedInfoSegment->CommandSize;

//
// Update __PRELINKED_INFO pointers to get them updated at a later stage.
//
Context->PrelinkedInfoSegment = (MACH_SEGMENT_COMMAND_64 *) Command.Address;
Context->PrelinkedInfoSection = &Context->PrelinkedInfoSegment->Sections[0];
}

EFI_STATUS
Expand All @@ -163,7 +201,7 @@ KcRebuildMachHeader (

CurrentSize = MachHeader->CommandsSize + sizeof (*MachHeader);
FilesetSize = InternalKcGetKextFilesetSize (Context);
RequiredSize = FilesetSize + sizeof (MACH_LOAD_COMMAND_SEGMENT_64);
RequiredSize = FilesetSize + sizeof (MACH_LOAD_COMMAND_SEGMENT_64) + Context->PrelinkedInfoSegment->CommandSize;

TextSegment = MachoGetSegmentByName64 (
&Context->PrelinkedMachContext,
Expand Down
35 changes: 29 additions & 6 deletions Library/OcAppleKernelLib/PrelinkedContext.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,12 +652,35 @@ PrelinkedInjectComplete (
return EFI_BUFFER_TOO_SMALL;
}

#if 0
//
// This is a potential optimisation for smaller kexts allowing us to use less space.
// This requires disable __KREMLIN relocation segment addition.
//
if (Context->IsKernelCollection && MACHO_ALIGN (ExportedInfoSize) <= Context->PrelinkedInfoSegment->Size) {
CopyMem (
&Context->Prelinked[Context->PrelinkedInfoSegment->FileOffset],
ExportedInfo,
ExportedInfoSize
);

ZeroMem (
&Context->Prelinked[Context->PrelinkedInfoSegment->FileOffset + ExportedInfoSize],
Context->PrelinkedInfoSegment->FileSize - ExportedInfoSize
);

FreePool (ExportedInfo);

return EFI_SUCCESS;
}
#endif

Context->PrelinkedInfoSegment->VirtualAddress = Context->PrelinkedLastAddress;
Context->PrelinkedInfoSegment->Size = ExportedInfoSize;
Context->PrelinkedInfoSegment->Size = MACHO_ALIGN (ExportedInfoSize);
Context->PrelinkedInfoSegment->FileOffset = Context->PrelinkedSize;
Context->PrelinkedInfoSegment->FileSize = ExportedInfoSize;
Context->PrelinkedInfoSegment->FileSize = MACHO_ALIGN (ExportedInfoSize);
Context->PrelinkedInfoSection->Address = Context->PrelinkedLastAddress;
Context->PrelinkedInfoSection->Size = ExportedInfoSize;
Context->PrelinkedInfoSection->Size = MACHO_ALIGN (ExportedInfoSize);
Context->PrelinkedInfoSection->Offset = Context->PrelinkedSize;

if (Context->IsKernelCollection) {
Expand All @@ -666,11 +689,11 @@ PrelinkedInjectComplete (
// in both inner and outer images.
//
Context->InnerInfoSegment->VirtualAddress = Context->PrelinkedLastAddress;
Context->InnerInfoSegment->Size = ExportedInfoSize;
Context->InnerInfoSegment->Size = MACHO_ALIGN (ExportedInfoSize);
Context->InnerInfoSegment->FileOffset = Context->PrelinkedSize;
Context->InnerInfoSegment->FileSize = ExportedInfoSize;
Context->InnerInfoSegment->FileSize = MACHO_ALIGN (ExportedInfoSize);
Context->InnerInfoSection->Address = Context->PrelinkedLastAddress;
Context->InnerInfoSection->Size = ExportedInfoSize;
Context->InnerInfoSection->Size = MACHO_ALIGN (ExportedInfoSize);
Context->InnerInfoSection->Offset = Context->PrelinkedSize;
}

Expand Down

0 comments on commit 2705377

Please sign in to comment.