2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Handle CoolCapture and KickTags (reset proof residents)
14 #include <aros/debug.h>
15 #include <exec/rawfmt.h>
16 #include <exec/resident.h>
17 #include <proto/exec.h>
19 #include "exec_debug.h"
20 #include "exec_intern.h"
21 #include "exec_util.h"
25 /* I don't think KickTag merge can be implemented without ugly hacks.. */
27 static IPTR
*CopyResidents(IPTR
*list
, IPTR
*dst
, IPTR
*oldlist
)
29 struct Resident
*RomTag
;
35 if (*list
& RESLIST_NEXT
)
37 list
= (IPTR
*)(*list
& ~RESLIST_NEXT
);
41 RomTag
= (struct Resident
*)*list
;
44 bug("* %p: %4d %02x %3d \"%s\"\n",
52 /* Try to find a resident with this name in original list */
53 oldresident
= InternalFindResident(RomTag
->rt_Name
, oldlist
);
57 * If found, check version.
58 * The resident is replaced if:
59 * a) Version of new resident is greater than version of old one.
60 * b) Versions are equal, but priority of new resident is greater than priority of old one.
62 struct Resident
*OldRomTag
= (struct Resident
*)*oldresident
;
64 if ((OldRomTag
->rt_Version
>= RomTag
->rt_Version
) ||
65 (OldRomTag
->rt_Version
== RomTag
->rt_Version
&& OldRomTag
->rt_Pri
>= RomTag
->rt_Pri
))
79 /* Terminate the list */
84 /* Count a number of residents in the list */
85 static int CountResidents(IPTR
*list
)
91 if (*list
& RESLIST_NEXT
)
93 list
= (IPTR
*)(*list
& ~RESLIST_NEXT
);
103 static void SortResidents(IPTR
*list
)
107 struct Resident
**RomTag
= (struct Resident
**)list
;
109 num
= CountResidents(list
);
114 for (i
= 0; i
< num
- 1; i
++)
116 if (RomTag
[i
]->rt_Pri
< RomTag
[i
+1]->rt_Pri
)
118 struct Resident
*tmp
;
121 RomTag
[i
+1] = RomTag
[i
];
131 * Residents in our list must always be sorted by priority.
132 * In order to maintain this, we can't just append new residents to the end of our list.
133 * We have to build a complete new list.
135 static void AddToResidentList(IPTR
*list
)
137 IPTR
*newlist
, *tmplist
;
138 int oldcnt
= CountResidents(SysBase
->ResModules
);
139 int addcnt
= CountResidents(list
);
141 /* Allocate space for the new list */
142 newlist
= AllocMem((oldcnt
+ addcnt
+ 1) * sizeof(struct Resident
*), MEMF_PUBLIC
);
146 /* Merge two lists and sort. */
147 tmplist
= CopyResidents(SysBase
->ResModules
, newlist
, NULL
);
148 CopyResidents(list
, tmplist
, SysBase
->ResModules
);
149 SortResidents(newlist
);
153 * We just drop the old list without deallocation because noone really knows if it's safe
154 * to deallocate it. With future page-based memory allocator it will certainly be not.
156 SysBase
->ResModules
= newlist
;
158 #ifndef NO_RUNTIME_DEBUG
159 if (SysBase
->ex_DebugFlags
& EXECDEBUGF_INITCODE
)
163 DINITCODE("Resident modules after KickTags merge:");
165 for (i
= 0; i
< addcnt
+ oldcnt
; i
++)
167 struct Resident
*RomTag
= (struct Resident
*)newlist
[i
];
169 NewRawDoFmt("+ %p: %4ld %02x %3ld \"%s\"\n", (VOID_FUNC
)RAWFMTFUNC_SERIAL
, NULL
,
170 RomTag
, RomTag
->rt_Pri
, RomTag
->rt_Flags
, RomTag
->rt_Version
, RomTag
->rt_Name
);
176 void InitKickTags(struct ExecBase
*SysBase
)
178 ULONG chk
= (ULONG
)(IPTR
)SysBase
->KickCheckSum
;
179 ULONG chkold
= SumKickData();
180 struct MemList
*ml
= (struct MemList
*)SysBase
->KickMemPtr
;
182 DINITCODE("kickmemptr=0x%p kicktagptr=0x%p kickchecksum=0x%08lx", SysBase
->KickMemPtr
, SysBase
->KickTagPtr
, chk
);
186 DINITCODE("Kicktag checksum mismatch %08lx!=%08lx", chkold
, chk
);
188 SysBase
->KickMemPtr
= NULL
;
189 SysBase
->KickTagPtr
= NULL
;
190 SysBase
->KickCheckSum
= 0;
196 * Before we do anything else, we need to lock down the entries in KickMemPtr
197 * If we get a single failure, don't run any of the KickTags.
199 while (ml
) /* single linked! */
203 DINITCODE("KickMemList 0x%p, NumEntries: %u", ml
->ml_NumEntries
);
204 for (i
= 0; i
< ml
->ml_NumEntries
; i
++)
206 DINITCODE(" + Addr 0x%p, Len %u", ml
->ml_ME
[i
].me_Addr
, ml
->ml_ME
[i
].me_Length
);
209 * Use the non-Munwalling AllocAbs, since regions may be consecutive.
210 * Mungwall headers can trash them in this case.
212 if (!InternalAllocAbs(ml
->ml_ME
[i
].me_Addr
, ml
->ml_ME
[i
].me_Length
, SysBase
))
214 DINITCODE("KickMem allocation failed");
215 /* Should we free already allocated KickMem lists? */
219 ml
= (struct MemList
*)ml
->ml_Node
.ln_Succ
;
222 if (SysBase
->KickTagPtr
)
224 AddToResidentList(SysBase
->KickTagPtr
);