1#
2# Create functions - start
3#
4
5function(create_system)
6  cmake_parse_arguments(OBJECT "" "ENTRY;FORMAT;NAME;OBJECT" "" ${ARGN})
7
8  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}          TRUE)
9  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_OBJ_TYPE SYSTEM)
10  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_NAME     ${OBJECT_NAME})
11  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_FORMAT   ${OBJECT_FORMAT})
12  set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_ENTRY    ${OBJECT_ENTRY})
13
14  set(${OBJECT_OBJECT} SYSTEM_${OBJECT_NAME} PARENT_SCOPE)
15endfunction()
16
17function(create_region)
18  cmake_parse_arguments(OBJECT "" "NAME;OBJECT;SIZE;START;FLAGS" "" ${ARGN})
19
20  if(DEFINED OBJECT_SIZE)
21    if(${OBJECT_SIZE} MATCHES "^([0-9]*)[kK]$")
22      math(EXPR OBJECT_SIZE "1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL)
23    elseif(${OBJECT_SIZE} MATCHES "^([0-9]*)[mM]$")
24      math(EXPR OBJECT_SIZE "1024 * 1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL)
25    elseif(NOT (${OBJECT_SIZE} MATCHES "^([0-9]*)$" OR ${OBJECT_SIZE} MATCHES "^0x([0-9a-fA-F]*)$"))
26      message(FATAL_ERROR "SIZE format is unknown.")
27    endif()
28  endif()
29
30  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}          TRUE)
31  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_OBJ_TYPE REGION)
32  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_NAME     ${OBJECT_NAME})
33  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_ADDRESS  ${OBJECT_START})
34  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_FLAGS    ${OBJECT_FLAGS})
35  set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_SIZE     ${OBJECT_SIZE})
36
37  set(${OBJECT_OBJECT} REGION_${OBJECT_NAME} PARENT_SCOPE)
38endfunction()
39
40function(get_parent)
41  cmake_parse_arguments(GET_PARENT "" "OBJECT;PARENT;TYPE" "" ${ARGN})
42
43  get_property(type GLOBAL PROPERTY ${GET_PARENT_OBJECT}_OBJ_TYPE)
44  if(${type} STREQUAL ${GET_PARENT_TYPE})
45    # Already the right type, so just set and return.
46    set(${GET_PARENT_PARENT} ${GET_PARENT_OBJECT} PARENT_SCOPE)
47    return()
48  endif()
49
50  get_property(parent GLOBAL PROPERTY ${GET_PARENT_OBJECT}_PARENT)
51  get_property(type   GLOBAL PROPERTY ${parent}_OBJ_TYPE)
52  while(NOT ${type} STREQUAL ${GET_PARENT_TYPE})
53    get_property(parent GLOBAL PROPERTY ${parent}_PARENT)
54    get_property(type   GLOBAL PROPERTY ${parent}_OBJ_TYPE)
55  endwhile()
56
57  set(${GET_PARENT_PARENT} ${parent} PARENT_SCOPE)
58endfunction()
59
60function(create_group)
61  cmake_parse_arguments(OBJECT "" "GROUP;LMA;NAME;OBJECT;SYMBOL;VMA" "" ${ARGN})
62
63  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}          TRUE)
64  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_OBJ_TYPE GROUP)
65  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_NAME     ${OBJECT_NAME})
66  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_SYMBOL   ${OBJECT_SYMBOL})
67
68  if(DEFINED OBJECT_GROUP)
69    find_object(OBJECT parent NAME ${OBJECT_GROUP})
70  else()
71    if(DEFINED OBJECT_VMA)
72      find_object(OBJECT obj NAME ${OBJECT_VMA})
73      get_parent(OBJECT ${obj} PARENT parent TYPE REGION)
74
75      get_property(vma GLOBAL PROPERTY ${parent}_NAME)
76      set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_VMA ${vma})
77    endif()
78
79    if(DEFINED OBJECT_LMA)
80      find_object(OBJECT obj NAME ${OBJECT_LMA})
81      get_parent(OBJECT ${obj} PARENT parent TYPE REGION)
82
83      get_property(lma GLOBAL PROPERTY ${parent}_NAME)
84      set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_LMA ${lma})
85    endif()
86  endif()
87
88  get_property(GROUP_FLAGS_INHERITED GLOBAL PROPERTY ${parent}_FLAGS)
89  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_FLAGS  ${GROUP_FLAGS_INHERITED})
90  set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_PARENT ${parent})
91
92  add_group(OBJECT ${parent} GROUP GROUP_${OBJECT_NAME})
93
94  set(${OBJECT_OBJECT} GROUP_${OBJECT_NAME} PARENT_SCOPE)
95endfunction()
96
97function(create_section)
98  set(single_args "NAME;ADDRESS;ALIGN_WITH_INPUT;TYPE;ALIGN;ENDALIGN;SUBALIGN;VMA;LMA;NOINPUT;NOINIT;NOSYMBOLS;GROUP;SYSTEM")
99  set(multi_args  "PASS")
100
101  cmake_parse_arguments(SECTION "" "${single_args}" "${multi_args}" ${ARGN})
102
103  if(DEFINED SECTION_PASS)
104    if(NOT (${SECTION_PASS} IN_LIST PASS))
105      # This section is not active in this pass, ignore.
106      return()
107    endif()
108  endif()
109
110  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME} TRUE)
111  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_OBJ_TYPE         SECTION)
112  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME             ${SECTION_NAME})
113  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ADDRESS          ${SECTION_ADDRESS})
114  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_TYPE             ${SECTION_TYPE})
115  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN            ${SECTION_ALIGN})
116  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN_WITH_INPUT ${SECTION_ALIGN_WITH_INPUT})
117  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SUBALIGN         ${SECTION_SUBALIGN})
118  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ENDALIGN         ${SECTION_ENDALIGN})
119  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINPUT          ${SECTION_NOINPUT})
120  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINIT           ${SECTION_NOINIT})
121  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOSYMBOLS        ${SECTION_NOSYMBOLS})
122
123  string(REGEX REPLACE "^[\.]" "" name_clean "${SECTION_NAME}")
124  string(REPLACE "." "_" name_clean "${name_clean}")
125  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME_CLEAN ${name_clean})
126
127  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_start      ${name_clean})
128  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_size       ${name_clean})
129  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_load_start ${name_clean})
130  set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end        ${name_clean})
131
132  set(INDEX 100)
133  set(settings_single "ALIGN;ANY;FIRST;KEEP;OFFSET;PRIO;SECTION;SORT")
134  set(settings_multi  "FLAGS;INPUT;PASS;SYMBOLS")
135  foreach(settings ${SECTION_SETTINGS})
136    if("${settings}" MATCHES "^{(.*)}$")
137      cmake_parse_arguments(SETTINGS "" "${settings_single}" "${settings_multi}" ${CMAKE_MATCH_1})
138
139      if(NOT ("${SETTINGS_SECTION}" STREQUAL "${SECTION_NAME}"))
140        continue()
141      endif()
142
143      if(DEFINED SETTINGS_PASS)
144        if(NOT (${SETTINGS_PASS} IN_LIST PASS))
145          # This section setting is not active in this pass, ignore.
146          continue()
147        endif()
148      endif()
149
150      if(DEFINED SETTINGS_PRIO)
151        set(idx ${SETTINGS_PRIO})
152      else()
153        set(idx ${INDEX})
154        math(EXPR INDEX "${INDEX} + 1")
155      endif()
156
157      foreach(setting ${settings_single} ${settings_multi})
158        set_property(GLOBAL PROPERTY
159          SECTION_${SECTION_NAME}_SETTING_${idx}_${setting}
160          ${SETTINGS_${setting}}
161        )
162        if(DEFINED SETTINGS_SORT)
163          set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end ${name_clean}_end)
164        endif()
165      endforeach()
166
167      set_property(GLOBAL APPEND PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${idx})
168
169    endif()
170  endforeach()
171
172  get_property(indicies GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES)
173  if(DEFINED indicies)
174    list(SORT indicies COMPARE NATURAL)
175    set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${indicies})
176  endif()
177
178  if(DEFINED SECTION_GROUP)
179    find_object(OBJECT parent NAME ${SECTION_GROUP})
180  elseif(DEFINED SECTION_VMA OR DEFINED SECTION_LMA)
181    if(DEFINED SECTION_VMA)
182      find_object(OBJECT object NAME ${SECTION_VMA})
183      get_parent(OBJECT ${object} PARENT parent TYPE REGION)
184
185      get_property(vma GLOBAL PROPERTY ${parent}_NAME)
186      set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_VMA ${vma})
187      set(SECTION_VMA ${vma})
188    endif()
189
190    if(DEFINED SECTION_LMA)
191      find_object(OBJECT object NAME ${SECTION_LMA})
192      get_parent(OBJECT ${object} PARENT parent TYPE REGION)
193
194      get_property(lma GLOBAL PROPERTY ${parent}_NAME)
195      set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_LMA ${lma})
196      set(SECTION_LMA ${lma})
197    endif()
198  else()
199    set(parent ${SECTION_SYSTEM})
200  endif()
201
202  set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_PARENT ${parent})
203  add_section(OBJECT ${parent} SECTION ${SECTION_NAME} ADDRESS ${SECTION_ADDRESS} VMA ${SECTION_VMA})
204endfunction()
205
206function(create_symbol)
207  cmake_parse_arguments(SYM "" "OBJECT;EXPR;SIZE;SUBALIGN;SYMBOL" "" ${ARGN})
208
209  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL} TRUE)
210  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_OBJ_TYPE SYMBOL)
211  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_NAME     ${SYM_SYMBOL})
212  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_EXPR     ${SYM_EXPR})
213  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SIZE     ${SYM_SIZE})
214  set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SYMBOL   ${SYM_SYMBOL})
215
216  set_property(GLOBAL PROPERTY SYMBOL_TABLE_${SYM_SYMBOL} ${SYM_SYMBOL})
217
218  add_symbol(OBJECT ${SYM_OBJECT} SYMBOL SYMBOL_${SYM_SYMBOL})
219endfunction()
220
221#
222# Create functions - end
223#
224
225#
226# Add functions - start
227#
228function(add_region)
229  cmake_parse_arguments(ADD_REGION "" "OBJECT;REGION" "" ${ARGN})
230
231  get_property(exists GLOBAL PROPERTY ${ADD_REGION_OBJECT})
232  if(NOT exists)
233    message(FATAL_ERROR
234      "Adding region ${ADD_REGION_REGION} to none-existing object: "
235      "${ADD_REGION_OBJECT}"
236    )
237  endif()
238
239  set_property(GLOBAL PROPERTY ${ADD_REGION_REGION}_PARENT ${ADD_REGION_OBJECT})
240  set_property(GLOBAL APPEND PROPERTY ${ADD_REGION_OBJECT}_REGIONS ${ADD_REGION_REGION})
241endfunction()
242
243function(add_group)
244  cmake_parse_arguments(ADD_GROUP "" "OBJECT;GROUP" "" ${ARGN})
245
246  get_property(exists GLOBAL PROPERTY ${ADD_GROUP_OBJECT})
247  if(NOT exists)
248    message(FATAL_ERROR
249      "Adding group ${ADD_GROUP_GROUP} to none-existing object: "
250      "${ADD_GROUP_OBJECT}"
251    )
252  endif()
253
254  get_property(vma GLOBAL PROPERTY ${ADD_GROUP_GROUP}_VMA)
255  get_property(object_name GLOBAL PROPERTY ${ADD_GROUP_OBJECT}_NAME)
256
257  if((NOT DEFINED vma) OR ("${vma}" STREQUAL ${object_name}))
258    set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_GROUPS ${ADD_GROUP_GROUP})
259  else()
260    set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_${vma}_GROUPS ${ADD_GROUP_GROUP})
261  endif()
262endfunction()
263
264function(add_section)
265  cmake_parse_arguments(ADD_SECTION "" "OBJECT;SECTION;ADDRESS;VMA" "" ${ARGN})
266
267  if(DEFINED ADD_SECTION_OBJECT)
268    get_property(type GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_OBJ_TYPE)
269    get_property(object_name GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_NAME)
270
271    if(NOT DEFINED type)
272      message(FATAL_ERROR
273              "Adding section ${ADD_SECTION_SECTION} to "
274              "none-existing object: ${ADD_SECTION_OBJECT}"
275      )
276    endif()
277  else()
278    set(ADD_SECTION_OBJECT RELOCATEABLE)
279  endif()
280
281  if("${ADD_SECTION_VMA}" STREQUAL "${object_name}" AND DEFINED ADD_SECTION_ADDRESS)
282    set_property(GLOBAL APPEND PROPERTY
283      ${ADD_SECTION_OBJECT}_SECTIONS_FIXED
284      SECTION_${ADD_SECTION_SECTION}
285    )
286  elseif(NOT DEFINED ADD_SECTION_VMA AND DEFINED SECTION_ADDRESS)
287    set_property(GLOBAL APPEND PROPERTY
288      ${ADD_SECTION_OBJECT}_SECTIONS_FIXED
289      SECTION_${ADD_SECTION_SECTION}
290    )
291  elseif("${ADD_SECTION_VMA}" STREQUAL "${object_name}")
292    set_property(GLOBAL APPEND PROPERTY
293      ${ADD_SECTION_OBJECT}_SECTIONS
294      SECTION_${ADD_SECTION_SECTION}
295    )
296  elseif(NOT DEFINED ADD_SECTION_VMA)
297    set_property(GLOBAL APPEND PROPERTY
298      ${ADD_SECTION_OBJECT}_SECTIONS
299      SECTION_${ADD_SECTION_SECTION}
300    )
301  elseif(DEFINED SECTION_ADDRESS)
302    set_property(GLOBAL APPEND PROPERTY
303      ${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS_FIXED
304      SECTION_${ADD_SECTION_SECTION}
305    )
306  else()
307    set_property(GLOBAL APPEND PROPERTY
308      ${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS
309      SECTION_${ADD_SECTION_SECTION}
310    )
311  endif()
312endfunction()
313
314function(add_symbol)
315  cmake_parse_arguments(ADD_SYMBOL "" "OBJECT;SYMBOL" "" ${ARGN})
316
317  # Section can be fixed address or not, VMA == LMA, .
318  #
319  get_property(exists GLOBAL PROPERTY ${ADD_SYMBOL_OBJECT})
320  if(NOT exists)
321    message(FATAL_ERROR
322      "Adding symbol ${ADD_SYMBOL_SYMBOL} to none-existing object: "
323      "${ADD_SYMBOL_OBJECT}"
324    )
325  endif()
326
327  set_property(GLOBAL APPEND PROPERTY ${ADD_SYMBOL_OBJECT}_SYMBOLS ${ADD_SYMBOL_SYMBOL})
328endfunction()
329
330#
331# Add functions - end
332#
333
334#
335# Retrieval functions - start
336#
337function(find_object)
338  cmake_parse_arguments(FIND "" "OBJECT;NAME" "" ${ARGN})
339
340  get_property(REGION  GLOBAL PROPERTY REGION_${FIND_NAME})
341  get_property(GROUP   GLOBAL PROPERTY GROUP_${FIND_NAME})
342  get_property(SECTION GLOBAL PROPERTY SECTION_${FIND_NAME})
343
344  if(REGION)
345    set(${FIND_OBJECT} REGION_${FIND_NAME} PARENT_SCOPE)
346  elseif(GROUP)
347    set(${FIND_OBJECT} GROUP_${FIND_NAME} PARENT_SCOPE)
348  elseif(SECTION)
349    set(${FIND_OBJECT} SECTION_${FIND_NAME} PARENT_SCOPE)
350  else()
351    message(WARNING "No object with name ${FIND_NAME} could be found.")
352  endif()
353endfunction()
354
355function(get_objects)
356  cmake_parse_arguments(GET "" "LIST;OBJECT;TYPE" "" ${ARGN})
357
358  get_property(type GLOBAL PROPERTY ${GET_OBJECT}_OBJ_TYPE)
359
360  if(${type} STREQUAL SECTION)
361    # A section doesn't have sub-items.
362    return()
363  endif()
364
365  if(NOT (${GET_TYPE} STREQUAL SECTION
366     OR   ${GET_TYPE} STREQUAL GROUP)
367  )
368    message(WARNING "Only retrieval of SECTION GROUP objects are supported.")
369    return()
370  endif()
371
372  set(out)
373
374  get_parent(OBJECT ${GET_OBJECT} PARENT parent TYPE SYSTEM)
375  get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
376  list(REMOVE_ITEM regions ${GET_OBJECT})
377
378  if(${GET_TYPE} STREQUAL SECTION)
379    get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS_FIXED)
380    list(APPEND out ${sections})
381
382    get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS)
383    foreach(group ${groups})
384      get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE})
385      list(APPEND out ${sections})
386    endforeach()
387
388    get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS)
389    list(APPEND out ${sections})
390
391    foreach(region ${regions})
392      get_property(vma GLOBAL PROPERTY ${region}_NAME)
393
394      get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS_FIXED)
395      list(APPEND out ${sections})
396
397      get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS)
398      foreach(group ${groups})
399        get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE})
400        list(APPEND out ${sections})
401      endforeach()
402
403      get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS)
404      list(APPEND out ${sections})
405    endforeach()
406  endif()
407
408  if(${GET_TYPE} STREQUAL GROUP)
409    get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS)
410    list(APPEND out ${groups})
411
412    foreach(group ${groups})
413      get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE})
414      list(APPEND out ${subgroups})
415    endforeach()
416
417    foreach(region ${regions})
418      get_property(vma GLOBAL PROPERTY ${region}_NAME)
419
420      get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS)
421      list(APPEND out ${groups})
422
423      foreach(group ${groups})
424        get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE})
425        list(APPEND out ${subgroups})
426      endforeach()
427    endforeach()
428  endif()
429
430  set(${GET_LIST} ${out} PARENT_SCOPE)
431endfunction()
432
433#
434# Retrieval functions - end
435#
436
437function(is_empty)
438  cmake_parse_arguments(IS_EMPTY "" "OBJECT" "" ${ARGN})
439
440  get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS_FIXED)
441  if(DEFINED sections)
442    set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
443    return()
444  endif()
445
446  get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_GROUPS)
447  if(DEFINED groups)
448    set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
449    return()
450  endif()
451
452
453  get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS)
454  if(DEFINED sections)
455    set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
456    return()
457  endif()
458
459  get_parent(OBJECT ${IS_EMPTY_OBJECT} PARENT parent TYPE SYSTEM)
460  get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
461  list(REMOVE_ITEM regions ${IS_EMPTY_OBJECT})
462  foreach(region ${regions})
463    get_property(vma GLOBAL PROPERTY ${region}_NAME)
464    get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS_FIXED)
465    if(DEFINED sections)
466      set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
467      return()
468    endif()
469
470    get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_GROUPS)
471    if(DEFINED groups)
472      set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
473      return()
474    endif()
475
476    get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS)
477    if(DEFINED sections)
478      set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
479      return()
480    endif()
481  endforeach()
482  set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY TRUE)
483endfunction()
484
485# This function post process the region for easier use.
486#
487# This is common post processing.
488# If the calling <linker>_script.cmake generator implements its own
489# process_region(), then the process_region_common() must be called explicitly
490# from the process_region() from the <linker>_script.cmake generator.
491#
492# This allows a custom <linker>_script.cmake generator to completely disable
493# the common post processing of regions.
494#
495# Tasks:
496# - Apply missing settings, such as initial address for first section in a region.
497# - Symbol names on sections
498# - Ordered list of all sections for easier retrieval on printing and configuration.
499function(process_region_common)
500  cmake_parse_arguments(REGION_COMMON "" "OBJECT" "" ${ARGN})
501
502  is_empty(OBJECT ${REGION_COMMON_OBJECT})
503
504  set(sections)
505  get_objects(LIST sections OBJECT ${REGION_COMMON_OBJECT} TYPE SECTION)
506  set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_SECTION_LIST_ORDERED ${sections})
507
508  set(groups)
509  get_objects(LIST groups OBJECT ${REGION_COMMON_OBJECT} TYPE GROUP)
510  set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_GROUP_LIST_ORDERED ${groups})
511
512  list(LENGTH sections section_count)
513  if(section_count GREATER 0)
514    list(GET sections 0 section)
515    get_property(address GLOBAL PROPERTY ${section}_ADDRESS)
516    if(NOT DEFINED address)
517      get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE REGION)
518      get_property(address GLOBAL PROPERTY ${parent}_ADDRESS)
519      set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address})
520    endif()
521  endif()
522
523  get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE SYSTEM)
524  get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
525  list(REMOVE_ITEM regions ${REGION_COMMON_OBJECT})
526  foreach(region ${regions})
527    get_property(vma GLOBAL PROPERTY ${region}_NAME)
528    set(sections_${vma})
529    get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS_FIXED)
530    list(APPEND sections_${vma} ${sections})
531
532    get_property(groups GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_GROUPS)
533    foreach(group ${groups})
534      get_objects(LIST sections OBJECT ${group} TYPE SECTION)
535      list(APPEND sections_${vma} ${sections})
536    endforeach()
537
538    get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS)
539    list(APPEND sections_${vma} ${sections})
540
541    list(LENGTH sections_${vma} section_count)
542    if(section_count GREATER 0)
543      list(GET sections_${vma} 0 section)
544      get_property(address GLOBAL PROPERTY ${section}_ADDRESS)
545      if(NOT DEFINED address)
546        get_property(address GLOBAL PROPERTY ${region}_ADDRESS)
547        set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address})
548      endif()
549    endif()
550  endforeach()
551endfunction()
552
553if(NOT COMMAND process_region)
554  function(process_region)
555    process_region_common(${ARGN})
556  endfunction()
557endif()
558
559
560#
561# String functions - start
562#
563# Each linker must implement their own <type>_to_string() functions to
564# generate a correct linker script.
565#
566if(NOT COMMAND system_to_string)
567  function(system_to_string)
568    message(WARNING "No linker defined function found. Please implement a "
569                    "system_to_string() function for this linker."
570    )
571  endfunction()
572endif()
573
574if(NOT COMMAND group_to_string)
575  function(group_to_string)
576    message(WARNING "No linker defined function found. Please implement a "
577                    "group_to_string() function for this linker."
578    )
579  endfunction()
580endif()
581
582if(NOT COMMAND section_to_string)
583  function(section_to_string)
584    message(WARNING "No linker defined function found. Please implement a "
585                    "section_to_string() function for this linker."
586    )
587  endfunction()
588endif()
589
590if(NOT COMMAND symbol_to_string)
591  function(symbol_to_string)
592    message(WARNING "No linker defined function found. Please implement a "
593                    "symbol_to_string() function for this linker."
594    )
595  endfunction()
596endif()
597
598function(to_string)
599  cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
600
601  get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE)
602
603  if("${type}" STREQUAL SYSTEM)
604    system_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING})
605  elseif(("${type}" STREQUAL REGION) OR ("${type}" STREQUAL GROUP))
606    group_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING})
607  elseif("${type}" STREQUAL SECTION)
608    section_to_string(SECTION ${STRING_OBJECT} STRING ${STRING_STRING})
609  elseif("${type}" STREQUAL SYMBOL)
610    symbol_to_string(SYMBOL ${STRING_OBJECT} STRING ${STRING_STRING})
611  endif()
612
613  set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
614endfunction()
615
616#
617# String functions - end
618#
619
620create_system(OBJECT new_system NAME ZEPHYR_LINKER_v1 FORMAT ${FORMAT} ENTRY ${ENTRY})
621
622# Sorting the memory sections in ascending order.
623foreach(region ${MEMORY_REGIONS})
624  if("${region}" MATCHES "^{(.*)}$")
625    cmake_parse_arguments(REGION "" "NAME;START" "" ${CMAKE_MATCH_1})
626    math(EXPR start_dec "${REGION_START}" OUTPUT_FORMAT DECIMAL)
627    set(region_id ${start_dec}_${REGION_NAME})
628    set(region_${region_id} ${region})
629    string(REPLACE ";" "\;" region_${region_id} "${region_${region_id}}")
630    list(APPEND region_sort ${region_id})
631  endif()
632endforeach()
633
634list(SORT region_sort COMPARE NATURAL)
635set(MEMORY_REGIONS_SORTED)
636foreach(region_start ${region_sort})
637  list(APPEND MEMORY_REGIONS_SORTED "${region_${region_start}}")
638endforeach()
639# sorting complete.
640
641foreach(region ${MEMORY_REGIONS_SORTED})
642  if("${region}" MATCHES "^{(.*)}$")
643    create_region(OBJECT new_region ${CMAKE_MATCH_1})
644
645    add_region(OBJECT ${new_system} REGION ${new_region})
646  endif()
647endforeach()
648
649foreach(group ${GROUPS})
650  if("${group}" MATCHES "^{(.*)}$")
651    create_group(OBJECT new_group ${CMAKE_MATCH_1})
652  endif()
653endforeach()
654
655foreach(section ${SECTIONS})
656  if("${section}" MATCHES "^{(.*)}$")
657    create_section(${CMAKE_MATCH_1} SYSTEM ${new_system})
658  endif()
659endforeach()
660
661foreach(symbol ${SYMBOLS})
662  if("${symbol}" MATCHES "^{(.*)}$")
663    create_symbol(OBJECT ${new_system} ${CMAKE_MATCH_1})
664  endif()
665endforeach()
666
667get_property(regions GLOBAL PROPERTY ${new_system}_REGIONS)
668foreach(region ${regions})
669  process_region(OBJECT ${region})
670endforeach()
671
672set(OUT)
673to_string(OBJECT ${new_system} STRING OUT)
674
675if(OUT_FILE)
676  file(WRITE ${OUT_FILE} "${OUT}")
677endif()
678